diff --git a/locales/ja.yml b/locales/ja.yml index 6f8b1eaf20..953556eedb 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -495,9 +495,6 @@ desktop/views/components/settings.vue: advanced-settings: "高度な設定" debug-mode: "デバッグモードを有効にする" debug-mode-desc: "この設定はブラウザに記憶されます。" - use-raw-script: "生のスクリプトを読み込む" - use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。" - source-info: "Misskeyはソースマップも提供しています。" experimental: "実験的機能を有効にする" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" tools: "ツール" diff --git a/package.json b/package.json index 119d2dac53..14f7956f52 100644 --- a/package.json +++ b/package.json @@ -211,6 +211,7 @@ "vue-template-compiler": "2.5.16", "vuedraggable": "2.16.0", "vuex": "3.0.1", + "vuex-persistedstate": "^2.5.4", "web-push": "3.3.1", "webfinger.js": "2.6.6", "webpack": "4.8.3", diff --git a/src/client/app/boot.js b/src/client/app/boot.js index 9338bc501e..e09a5d12e9 100644 --- a/src/client/app/boot.js +++ b/src/client/app/boot.js @@ -29,11 +29,21 @@ if (url.pathname == '/auth') app = 'auth'; //#endregion - // Detect the user language - // Note: The default language is Japanese + //#region Detect the user language let lang = navigator.language.split('-')[0]; + + // The default language is English if (!LANGS.includes(lang)) lang = 'en'; - if (localStorage.getItem('lang')) lang = localStorage.getItem('lang'); + + const vuex = localStorage.getItem('vuex'); + if (vuex) { + const data = JSON.parse(vuex); + if (data.device.lang) lang = data.device.lang; + } + + const storedLang = localStorage.getItem('lang'); + if (storedLang) lang = storedLang; + //#endregion // Detect the user agent const ua = navigator.userAgent.toLowerCase(); @@ -68,13 +78,6 @@ // Script version const ver = localStorage.getItem('v') || VERSION; - // Whether in debug mode - const isDebug = localStorage.getItem('debug') == 'true'; - - // Whether use raw version script - const raw = (localStorage.getItem('useRawScript') == 'true' && isDebug) - || ENV != 'production'; - // Get salt query const salt = localStorage.getItem('salt') ? '?salt=' + localStorage.getItem('salt') @@ -84,7 +87,7 @@ // 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}.${ver}.${lang}.${raw ? 'raw' : 'min'}.js${salt}`); + script.setAttribute('src', `/assets/${app}.${ver}.${lang}.js${salt}`); script.setAttribute('async', 'true'); script.setAttribute('defer', 'true'); head.appendChild(script); diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue index 8cc72fb518..6b407ccc80 100644 --- a/src/client/app/common/views/components/avatar.vue +++ b/src/client/app/common/views/components/avatar.vue @@ -22,7 +22,7 @@ export default Vue.extend({ }, computed: { lightmode(): boolean { - return localStorage.getItem('lightmode') == 'true'; + return this.$store.state.device.lightmode; }, style(): any { return { diff --git a/src/client/app/common/views/components/messaging-room.vue b/src/client/app/common/views/components/messaging-room.vue index 330834233a..7832a331df 100644 --- a/src/client/app/common/views/components/messaging-room.vue +++ b/src/client/app/common/views/components/messaging-room.vue @@ -149,9 +149,9 @@ export default Vue.extend({ onMessage(message) { // サウンドを再生する - if ((this as any).os.isEnableSounds) { + if (this.$store.state.device.enableSounds) { const sound = new Audio(`${url}/assets/message.mp3`); - sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; + sound.volume = this.$store.state.device.soundVolume; sound.play(); } diff --git a/src/client/app/common/views/components/othello.game.vue b/src/client/app/common/views/components/othello.game.vue index 8c646cce07..ea75558d10 100644 --- a/src/client/app/common/views/components/othello.game.vue +++ b/src/client/app/common/views/components/othello.game.vue @@ -162,9 +162,9 @@ export default Vue.extend({ this.o.put(this.myColor, pos); // サウンドを再生する - if ((this as any).os.isEnableSounds) { + if (this.$store.state.device.enableSounds) { const sound = new Audio(`${url}/assets/othello-put-me.mp3`); - sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; + sound.volume = this.$store.state.device.soundVolume; sound.play(); } @@ -186,9 +186,9 @@ export default Vue.extend({ this.$forceUpdate(); // サウンドを再生する - if ((this as any).os.isEnableSounds && x.color != this.myColor) { + if (this.$store.state.device.enableSounds && x.color != this.myColor) { const sound = new Audio(`${url}/assets/othello-put-you.mp3`); - sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; + sound.volume = this.$store.state.device.soundVolume; sound.play(); } }, diff --git a/src/client/app/config.ts b/src/client/app/config.ts index 522d7ff056..70c085de1c 100644 --- a/src/client/app/config.ts +++ b/src/client/app/config.ts @@ -8,6 +8,7 @@ declare const _STATS_URL_: string; declare const _STATUS_URL_: string; declare const _DEV_URL_: string; declare const _LANG_: string; +declare const _LANGS_: string; declare const _RECAPTCHA_SITEKEY_: string; declare const _SW_PUBLICKEY_: string; declare const _THEME_COLOR_: string; @@ -27,6 +28,7 @@ export const statsUrl = _STATS_URL_; export const statusUrl = _STATUS_URL_; export const devUrl = _DEV_URL_; export const lang = _LANG_; +export const langs = _LANGS_; export const recaptchaSitekey = _RECAPTCHA_SITEKEY_; export const swPublickey = _SW_PUBLICKEY_; export const themeColor = _THEME_COLOR_; diff --git a/src/client/app/desktop/views/components/home.vue b/src/client/app/desktop/views/components/home.vue index 87dae5a806..d84c1e404f 100644 --- a/src/client/app/desktop/views/components/home.vue +++ b/src/client/app/desktop/views/components/home.vue @@ -102,7 +102,7 @@ export default Vue.extend({ computed: { home(): any[] { - return this.$store.state.settings.data.home; + return this.$store.state.settings.home; }, left(): any[] { return this.home.filter(w => w.place == 'left'); diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue index c041e5278c..55b0de3fbd 100644 --- a/src/client/app/desktop/views/components/notes.vue +++ b/src/client/app/desktop/views/components/notes.vue @@ -145,9 +145,9 @@ export default Vue.extend({ this.notes.unshift(note); // サウンドを再生する - if ((this as any).os.isEnableSounds && !silent) { + if (this.$store.state.device.enableSounds && !silent) { const sound = new Audio(`${url}/assets/post.mp3`); - sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; + sound.volume = this.$store.state.device.soundVolume; sound.play(); } diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue index 24af64a59c..3fe09b9acc 100644 --- a/src/client/app/desktop/views/components/settings.vue +++ b/src/client/app/desktop/views/components/settings.vue @@ -62,8 +62,10 @@ @@ -77,14 +79,10 @@

%i18n:@language%

- + - - - - - +
@@ -178,15 +176,7 @@ %i18n:@debug-mode-desc% - - + %i18n:@experimental-desc%
@@ -214,7 +204,7 @@ import XApi from './settings.api.vue'; import XApps from './settings.apps.vue'; import XSignins from './settings.signins.vue'; import XDrive from './settings.drive.vue'; -import { url, docsUrl, license, lang, version } from '../../../config'; +import { url, docsUrl, license, lang, langs, version } from '../../../config'; import checkForUpdate from '../../../common/scripts/check-for-update'; import MkTaskManager from './taskmanager.vue'; @@ -235,55 +225,60 @@ export default Vue.extend({ meta: null, license, version, + langs, latestVersion: undefined, checkingForUpdate: false, - darkmode: localStorage.getItem('darkmode') == 'true', - enableSounds: localStorage.getItem('enableSounds') == 'true', - autoPopout: localStorage.getItem('autoPopout') == 'true', - apiViaStream: localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true, - soundVolume: localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) : 50, - lang: localStorage.getItem('lang') || '', - preventUpdate: localStorage.getItem('preventUpdate') == 'true', - debug: localStorage.getItem('debug') == 'true', - useRawScript: localStorage.getItem('useRawScript') == 'true', - enableExperimental: localStorage.getItem('enableExperimental') == 'true' + darkmode: localStorage.getItem('darkmode') == 'true' }; }, computed: { licenseUrl(): string { return `${docsUrl}/${lang}/license`; + }, + + apiViaStream: { + get() { return this.$store.state.device.apiViaStream; }, + set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); } + }, + + autoPopout: { + get() { return this.$store.state.device.autoPopout; }, + set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); } + }, + + enableSounds: { + get() { return this.$store.state.device.enableSounds; }, + set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); } + }, + + soundVolume: { + get() { return this.$store.state.device.soundVolume; }, + set(value) { this.$store.commit('device/set', { key: 'soundVolume', value }); } + }, + + lang: { + get() { return this.$store.state.device.lang; }, + set(value) { this.$store.commit('device/set', { key: 'lang', value }); } + }, + + preventUpdate: { + get() { return this.$store.state.device.preventUpdate; }, + set(value) { this.$store.commit('device/set', { key: 'preventUpdate', value }); } + }, + + debug: { + get() { return this.$store.state.device.debug; }, + set(value) { this.$store.commit('device/set', { key: 'debug', value }); } + }, + + enableExperimentalFeatures: { + get() { return this.$store.state.device.enableExperimentalFeatures; }, + set(value) { this.$store.commit('device/set', { key: 'enableExperimentalFeatures', value }); } } }, watch: { - autoPopout() { - localStorage.setItem('autoPopout', this.autoPopout ? 'true' : 'false'); - }, - apiViaStream() { - localStorage.setItem('apiViaStream', this.apiViaStream ? 'true' : 'false'); - }, darkmode() { (this as any)._updateDarkmode_(this.darkmode); - }, - enableSounds() { - localStorage.setItem('enableSounds', this.enableSounds ? 'true' : 'false'); - }, - soundVolume() { - localStorage.setItem('soundVolume', this.soundVolume.toString()); - }, - lang() { - localStorage.setItem('lang', this.lang); - }, - preventUpdate() { - localStorage.setItem('preventUpdate', this.preventUpdate ? 'true' : 'false'); - }, - debug() { - localStorage.setItem('debug', this.debug ? 'true' : 'false'); - }, - useRawScript() { - localStorage.setItem('useRawScript', this.useRawScript ? 'true' : 'false'); - }, - enableExperimental() { - localStorage.setItem('enableExperimental', this.enableExperimental ? 'true' : 'false'); } }, created() { @@ -391,7 +386,7 @@ export default Vue.extend({ }, soundTest() { const sound = new Audio(`${url}/assets/message.mp3`); - sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; + sound.volume = this.$store.state.device.soundVolume; sound.play(); } } diff --git a/src/client/app/desktop/views/components/window.vue b/src/client/app/desktop/views/components/window.vue index ac84c2bd62..7ee1da12ba 100644 --- a/src/client/app/desktop/views/components/window.vue +++ b/src/client/app/desktop/views/components/window.vue @@ -95,7 +95,7 @@ export default Vue.extend({ }, created() { - if (localStorage.getItem('autoPopout') == 'true' && this.popoutUrl) { + if (this.$store.state.device.autoPopout && this.popoutUrl) { this.popout(); this.preventMount = true; } else { diff --git a/src/client/app/init.ts b/src/client/app/init.ts index fd04f9bcc3..34bc6a2785 100644 --- a/src/client/app/init.ts +++ b/src/client/app/init.ts @@ -147,7 +147,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API) os, api: os.api, apis: os.apis, - clientSettings: os.store.state.settings.data + clientSettings: os.store.state.settings }; } }); @@ -173,7 +173,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API) } //#region 更新チェック - const preventUpdate = localStorage.getItem('preventUpdate') == 'true'; + const preventUpdate = os.store.state.device.preventUpdate; if (!preventUpdate) { setTimeout(() => { checkForUpdate(os); diff --git a/src/client/app/mios.ts b/src/client/app/mios.ts index 2373b0d8d2..a5a38a5414 100644 --- a/src/client/app/mios.ts +++ b/src/client/app/mios.ts @@ -98,14 +98,7 @@ export default class MiOS extends EventEmitter { * Whether is debug mode */ public get debug() { - return localStorage.getItem('debug') == 'true'; - } - - /** - * Whether enable sounds - */ - public get isEnableSounds() { - return localStorage.getItem('enableSounds') == 'true'; + return this.store ? this.store.state.device.debug : false; } public store: ReturnType; @@ -435,12 +428,8 @@ export default class MiOS extends EventEmitter { }); }); - // Whether use raw version script - const raw = (localStorage.getItem('useRawScript') == 'true' && this.debug) - || process.env.NODE_ENV != 'production'; - // The path of service worker script - const sw = `/sw.${version}.${lang}.${raw ? 'raw' : 'min'}.js`; + const sw = `/sw.${version}.${lang}.js`; // Register service worker navigator.serviceWorker.register(sw).then(registration => { @@ -471,8 +460,7 @@ export default class MiOS extends EventEmitter { }; const promise = new Promise((resolve, reject) => { - const viaStream = this.stream && this.stream.hasConnection && - (localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true); + const viaStream = this.stream && this.stream.hasConnection && this.store.state.device.apiViaStream; if (viaStream) { const stream = this.stream.borrow(); diff --git a/src/client/app/mobile/views/components/media-image.vue b/src/client/app/mobile/views/components/media-image.vue index d4ee0c66a9..c4622b01a7 100644 --- a/src/client/app/mobile/views/components/media-image.vue +++ b/src/client/app/mobile/views/components/media-image.vue @@ -17,7 +17,7 @@ export default Vue.extend({ }, computed: { lightmode(): boolean { - return localStorage.getItem('lightmode') == 'true'; + return this.$store.state.device.lightmode; }, style(): any { return { diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue index 55c7895a90..3b0df87549 100644 --- a/src/client/app/mobile/views/pages/settings.vue +++ b/src/client/app/mobile/views/pages/settings.vue @@ -71,11 +71,7 @@ - 日本語 - English - Français - Polski - Deutsch + {{ x[1] }} @@ -122,7 +118,7 @@