From 6ba1035b69e8a3c4413d343b893ea6d9254e951f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sat, 3 Mar 2018 07:32:18 +0900
Subject: [PATCH] nanka iroiro

Closes #1168, #1169
---
 .gitignore                                        |  2 ++
 package.json                                      |  2 ++
 src/version.ts                                    |  2 +-
 src/web/app/boot.js                               |  4 +++-
 src/web/app/common/scripts/check-for-update.ts    | 10 ++++++----
 src/web/app/common/views/components/switch.vue    |  6 +++++-
 src/web/app/desktop/views/components/settings.vue | 11 ++++++++++-
 webpack/plugins/consts.ts                         |  4 +++-
 webpack/plugins/index.ts                          |  9 +++++++++
 webpack/webpack.config.ts                         |  6 ++++--
 10 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/.gitignore b/.gitignore
index a51e70381e..1c05ba5f2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ npm-debug.log
 run.bat
 api-docs.json
 package-lock.json
+version.json
+/.cache-loader
diff --git a/package.json b/package.json
index 03db892ec6..a4ab2dfeb7 100644
--- a/package.json
+++ b/package.json
@@ -124,6 +124,7 @@
 		"gulp-typescript": "3.2.4",
 		"gulp-uglify": "3.0.0",
 		"gulp-util": "3.0.8",
+		"hard-source-webpack-plugin": "^0.6.1",
 		"highlight.js": "9.12.0",
 		"html-minifier": "3.5.9",
 		"inquirer": "5.1.0",
@@ -144,6 +145,7 @@
 		"node-sass": "^4.7.2",
 		"node-sass-json-importer": "^3.1.3",
 		"nprogress": "0.2.0",
+		"on-build-webpack": "^0.1.0",
 		"os-utils": "0.0.14",
 		"progress-bar-webpack-plugin": "^1.11.0",
 		"prominence": "0.2.0",
diff --git a/src/version.ts b/src/version.ts
index 2b4c1320e7..d379b57f8f 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -2,6 +2,6 @@
  * Version
  */
 
-const meta = require('../package.json');
+const meta = require('../version.json');
 
 export default meta.version as string;
diff --git a/src/web/app/boot.js b/src/web/app/boot.js
index 211dc2f883..91830b6c03 100644
--- a/src/web/app/boot.js
+++ b/src/web/app/boot.js
@@ -61,11 +61,13 @@
 		app = isMobile ? 'mobile' : 'desktop';
 	}
 
+	const ver = localStorage.getItem('v') || VERSION;
+
 	// Load an app script
 	// Note: 'async' make it possible to load the script asyncly.
 	//       'defer' make it possible to run the script when the dom loaded.
 	const script = document.createElement('script');
-	script.setAttribute('src', `/assets/${app}.${VERSION}.${lang}.js`);
+	script.setAttribute('src', `/assets/${app}.${ver}.${lang}.js`);
 	script.setAttribute('async', 'true');
 	script.setAttribute('defer', 'true');
 	head.appendChild(script);
diff --git a/src/web/app/common/scripts/check-for-update.ts b/src/web/app/common/scripts/check-for-update.ts
index 3e7eb79d8b..81c1eb9812 100644
--- a/src/web/app/common/scripts/check-for-update.ts
+++ b/src/web/app/common/scripts/check-for-update.ts
@@ -1,11 +1,13 @@
 import MiOS from '../mios';
-import { version } from '../../config';
+import { version as current } from '../../config';
 
 export default async function(mios: MiOS, force = false, silent = false) {
 	const meta = await mios.getMeta(force);
+	const newer = meta.version;
 
-	if (meta.version != version) {
+	if (newer != current) {
 		localStorage.setItem('should-refresh', 'true');
+		localStorage.setItem('v', newer);
 
 		// Clear cache (serive worker)
 		try {
@@ -21,10 +23,10 @@ export default async function(mios: MiOS, force = false, silent = false) {
 		}
 
 		if (!silent) {
-			alert('%i18n:common.update-available%'.replace('{newer}', meta.version).replace('{current}', version));
+			alert('%i18n:common.update-available%'.replace('{newer}', newer).replace('{current}', current));
 		}
 
-		return meta.version;
+		return newer;
 	} else {
 		return null;
 	}
diff --git a/src/web/app/common/views/components/switch.vue b/src/web/app/common/views/components/switch.vue
index fc12e00540..bfb951dfa1 100644
--- a/src/web/app/common/views/components/switch.vue
+++ b/src/web/app/common/views/components/switch.vue
@@ -86,6 +86,7 @@ export default Vue.extend({
 <style lang="stylus" scoped>
 .mk-switch
 	display flex
+	margin 8px 0
 	cursor pointer
 	transition all 0.3s
 
@@ -134,7 +135,9 @@ export default Vue.extend({
 		display inline-block
 		margin 0
 		width 40px
+		min-width 40px
 		height 20px
+		min-height 20px
 		background #dcdfe6
 		border 1px solid #dcdfe6
 		outline none
@@ -154,17 +157,18 @@ export default Vue.extend({
 	> .label
 		margin-left 8px
 		display block
-		font-size 14px
 		cursor pointer
 		transition inherit
 
 		> span
+			display block
 			line-height 20px
 			color #4a535a
 			transition inherit
 
 		> p
 			margin 0
+			font-size 90%
 			color #9daab3
 
 </style>
diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue
index 4a9db5f48b..0c1968f67a 100644
--- a/src/web/app/desktop/views/components/settings.vue
+++ b/src/web/app/desktop/views/components/settings.vue
@@ -94,6 +94,9 @@
 			<mk-switch v-model="debug" text="デバッグモードを有効にする">
 				<span>この設定はアカウントに保存されません。</span>
 			</mk-switch>
+			<mk-switch v-model="enableExperimental" text="実験的機能を有効にする">
+				<span>この設定はアカウントに保存されません。実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。</span>
+			</mk-switch>
 		</section>
 
 		<section class="other" v-show="page == 'other'">
@@ -126,17 +129,22 @@ export default Vue.extend({
 	data() {
 		return {
 			page: 'profile',
+			meta: null,
 			license,
 			version,
 			latestVersion: undefined,
 			checkingForUpdate: false,
 			showPostFormOnTopOfTl: false,
-			debug: localStorage.getItem('debug') == 'true'
+			debug: localStorage.getItem('debug') == 'true',
+			enableExperimental: localStorage.getItem('enableExperimental') == 'true'
 		};
 	},
 	watch: {
 		debug() {
 			localStorage.setItem('debug', this.debug ? 'true' : 'false');
+		},
+		enableExperimental() {
+			localStorage.setItem('enableExperimental', this.enableExperimental ? 'true' : 'false');
 		}
 	},
 	computed: {
@@ -145,6 +153,7 @@ export default Vue.extend({
 		}
 	},
 	created() {
+		this.meta = (this as any).os.getMeta();
 		this.showPostFormOnTopOfTl = (this as any).os.i.client_settings.showPostFormOnTopOfTl;
 	},
 	methods: {
diff --git a/webpack/plugins/consts.ts b/webpack/plugins/consts.ts
index a01c18af6f..cb9ba8e86f 100644
--- a/webpack/plugins/consts.ts
+++ b/webpack/plugins/consts.ts
@@ -4,7 +4,9 @@
 
 import * as webpack from 'webpack';
 
-import version from '../../src/version';
+const meta = require('../../package.json');
+const version = meta.version;
+
 const constants = require('../../src/const.json');
 import config from '../../src/conf';
 import { licenseHtml } from '../../src/common/build/license';
diff --git a/webpack/plugins/index.ts b/webpack/plugins/index.ts
index b97cde231d..4023cd6cba 100644
--- a/webpack/plugins/index.ts
+++ b/webpack/plugins/index.ts
@@ -1,4 +1,7 @@
+import * as fs from 'fs';
 import * as webpack from 'webpack';
+const WebpackOnBuildPlugin = require('on-build-webpack');
+const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
 const ProgressBarPlugin = require('progress-bar-webpack-plugin');
 import chalk from 'chalk';
 
@@ -11,6 +14,7 @@ const isProduction = env === 'production';
 
 export default (version, lang) => {
 	const plugins = [
+		new HardSourceWebpackPlugin(),
 		new ProgressBarPlugin({
 			format: chalk`  {cyan.bold yes we can} {bold [}:bar{bold ]} {green.bold :percent} {gray (:current/:total)} :elapseds`,
 			clear: false
@@ -20,6 +24,11 @@ export default (version, lang) => {
 			'process.env': {
 				NODE_ENV: JSON.stringify(process.env.NODE_ENV)
 			}
+		}),
+		new WebpackOnBuildPlugin(stats => {
+			fs.writeFileSync('./version.json', JSON.stringify({
+				version
+			}), 'utf-8');
 		})
 	];
 
diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts
index a873419450..cfb1299708 100644
--- a/webpack/webpack.config.ts
+++ b/webpack/webpack.config.ts
@@ -12,7 +12,8 @@ const constants = require('../src/const.json');
 import plugins from './plugins';
 
 import langs from '../locales';
-import version from '../src/version';
+const meta = require('../package.json');
+const version = meta.version;
 
 global['faReplacement'] = faReplacement;
 
@@ -59,7 +60,7 @@ module.exports = Object.keys(langs).map(lang => {
 			rules: [{
 				test: /\.vue$/,
 				exclude: /node_modules/,
-				use: [/*'cache-loader', */{
+				use: ['cache-loader', {
 					loader: 'vue-loader',
 					options: {
 						cssSourceMap: false,
@@ -140,6 +141,7 @@ module.exports = Object.keys(langs).map(lang => {
 				use: [{
 					loader: 'ts-loader',
 					options: {
+						happyPackMode: true,
 						configFile: __dirname + '/../src/web/app/tsconfig.json',
 						appendTsSuffixTo: [/\.vue$/]
 					}