From faf2c007aab3a096129dd218b44d8f01a6f5ad87 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 12 Apr 2021 22:07:32 +0900
Subject: [PATCH] fix bug

---
 src/client/init.ts                  | 30 ++++++++++++----
 src/client/pages/settings/theme.vue | 56 +++++++++++++++++------------
 src/client/pages/theme-editor.vue   |  4 +--
 src/client/scripts/theme.ts         | 16 ++++-----
 src/client/store.ts                 |  6 ++--
 src/client/theme-store.ts           |  1 -
 6 files changed, 69 insertions(+), 44 deletions(-)

diff --git a/src/client/init.ts b/src/client/init.ts
index e77e53dc64..daedce4aee 100644
--- a/src/client/init.ts
+++ b/src/client/init.ts
@@ -6,7 +6,7 @@ import '@client/style.scss';
 
 import * as Sentry from '@sentry/browser';
 import { Integrations } from '@sentry/tracing';
-import { createApp, watch } from 'vue';
+import { computed, createApp, watch } from 'vue';
 import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
 
 import widgets from '@client/widgets';
@@ -25,7 +25,6 @@ import { fetchInstance, instance } from '@client/instance';
 import { makeHotkey } from '@client/scripts/hotkey';
 import { search } from '@client/scripts/search';
 import { isMobile } from '@client/scripts/is-mobile';
-import { getThemes } from '@client/theme-store';
 import { initializeSw } from '@client/scripts/initialize-sw';
 import { reloadChannel } from '@client/scripts/unison-reload';
 import { reactionPicker } from '@client/scripts/reaction-picker';
@@ -36,6 +35,13 @@ console.info(`Misskey v${version}`);
 window.onerror = null;
 window.onunhandledrejection = null;
 
+// 後方互換性のため。
+// TODO: そのうち消す
+if ((typeof ColdDeviceStorage.get('lightTheme') === 'string') || (typeof ColdDeviceStorage.get('darkTheme') === 'string')) {
+	ColdDeviceStorage.set('lightTheme', require('@client/themes/l-light.json5'));
+	ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.json5'));
+}
+
 if (_DEV_) {
 	console.warn('Development mode!!!');
 
@@ -205,12 +211,24 @@ if (splash) {
 }
 
 watch(defaultStore.reactiveState.darkMode, (darkMode) => {
-	import('@client/scripts/theme').then(({ builtinThemes }) => {
-		const themes = builtinThemes.concat(getThemes());
-		applyTheme(themes.find(x => x.id === (darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'))));
-	});
+	applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
 }, { immediate: localStorage.theme == null });
 
+const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
+const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
+
+watch(darkTheme, (theme) => {
+	if (defaultStore.state.darkMode) {
+		applyTheme(theme);
+	}
+});
+
+watch(lightTheme, (theme) => {
+	if (!defaultStore.state.darkMode) {
+		applyTheme(theme);
+	}
+});
+
 //#region Sync dark mode
 if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
 	defaultStore.set('darkMode', isDeviceDarkmode());
diff --git a/src/client/pages/settings/theme.vue b/src/client/pages/settings/theme.vue
index 75f27d12e7..606e10ab7a 100644
--- a/src/client/pages/settings/theme.vue
+++ b/src/client/pages/settings/theme.vue
@@ -27,7 +27,7 @@
 	</FormGroup>
 
 	<template v-if="darkMode">
-		<FormSelect v-model:value="darkTheme">
+		<FormSelect v-model:value="darkThemeId">
 			<template #label>{{ $ts.themeForDarkMode }}</template>
 			<optgroup :label="$ts.darkThemes">
 				<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@@ -36,7 +36,7 @@
 				<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
 			</optgroup>
 		</FormSelect>
-		<FormSelect v-model:value="lightTheme">
+		<FormSelect v-model:value="lightThemeId">
 			<template #label>{{ $ts.themeForLightMode }}</template>
 			<optgroup :label="$ts.lightThemes">
 				<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@@ -47,7 +47,7 @@
 		</FormSelect>
 	</template>
 	<template v-else>
-		<FormSelect v-model:value="lightTheme">
+		<FormSelect v-model:value="lightThemeId">
 			<template #label>{{ $ts.themeForLightMode }}</template>
 			<optgroup :label="$ts.lightThemes">
 				<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@@ -56,7 +56,7 @@
 				<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
 			</optgroup>
 		</FormSelect>
-		<FormSelect v-model:value="darkTheme">
+		<FormSelect v-model:value="darkThemeId">
 			<template #label>{{ $ts.themeForDarkMode }}</template>
 			<optgroup :label="$ts.darkThemes">
 				<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@@ -77,7 +77,7 @@
 
 	<FormGroup>
 		<FormLink to="/theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }}</FormLink>
-		<FormLink to="/advanced-theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }} ({{ $ts.advanced }})</FormLink>
+		<!--<FormLink to="/advanced-theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }} ({{ $ts.advanced }})</FormLink>-->
 	</FormGroup>
 
 	<FormLink to="/settings/theme/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink>
@@ -85,7 +85,7 @@
 </template>
 
 <script lang="ts">
-import { computed, defineComponent, onMounted, ref, watch } from 'vue';
+import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue';
 import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye, faGlobe, faPaintRoller } from '@fortawesome/free-solid-svg-icons';
 import FormSwitch from '@client/components/form/switch.vue';
 import FormSelect from '@client/components/form/select.vue';
@@ -93,7 +93,7 @@ import FormBase from '@client/components/form/base.vue';
 import FormGroup from '@client/components/form/group.vue';
 import FormLink from '@client/components/form/link.vue';
 import FormButton from '@client/components/form/button.vue';
-import { builtinThemes, applyTheme } from '@client/scripts/theme';
+import { builtinThemes } from '@client/scripts/theme';
 import { selectFile } from '@client/scripts/select-file';
 import { isDeviceDarkmode } from '@client/scripts/is-device-darkmode';
 import { ColdDeviceStorage } from '@client/store';
@@ -124,25 +124,29 @@ export default defineComponent({
 		const themes = computed(() => builtinThemes.concat(installedThemes.value));
 		const darkThemes = computed(() => themes.value.filter(t => t.base == 'dark' || t.kind == 'dark'));
 		const lightThemes = computed(() => themes.value.filter(t => t.base == 'light' || t.kind == 'light'));
-		const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
-		const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
+		const darkTheme = ColdDeviceStorage.ref('darkTheme');
+		const darkThemeId = computed({
+			get() {
+				return darkTheme.value.id;
+			},
+			set(id) {
+				ColdDeviceStorage.set('darkTheme', themes.value.find(x => x.id === id))
+			}
+		});
+		const lightTheme = ColdDeviceStorage.ref('lightTheme');
+		const lightThemeId = computed({
+			get() {
+				return lightTheme.value.id;
+			},
+			set(id) {
+				ColdDeviceStorage.set('lightTheme', themes.value.find(x => x.id === id))
+			}
+		});
 		const darkMode = computed(defaultStore.makeGetterSetter('darkMode'));
 		const syncDeviceDarkMode = computed(ColdDeviceStorage.makeGetterSetter('syncDeviceDarkMode'));
 		const wallpaper = ref(localStorage.getItem('wallpaper'));
 		const themesCount = installedThemes.value.length;
 
-		watch(darkTheme, () => {
-			if (defaultStore.state.darkMode) {
-				applyTheme(themes.value.find(x => x.id === darkTheme.value));
-			}
-		});
-
-		watch(lightTheme, () => {
-			if (!defaultStore.state.darkMode) {
-				applyTheme(themes.value.find(x => x.id === lightTheme.value));
-			}
-		});
-
 		watch(syncDeviceDarkMode, () => {
 			if (syncDeviceDarkMode) {
 				defaultStore.set('darkMode', isDeviceDarkmode());
@@ -162,6 +166,12 @@ export default defineComponent({
 			emit('info', INFO);
 		});
 
+		onActivated(() => {
+			fetchThemes().then(() => {
+				installedThemes.value = getThemes();
+			});
+		});
+
 		fetchThemes().then(() => {
 			installedThemes.value = getThemes();
 		});
@@ -170,8 +180,8 @@ export default defineComponent({
 			[symbols.PAGE_INFO]: INFO,
 			darkThemes,
 			lightThemes,
-			darkTheme,
-			lightTheme,
+			darkThemeId,
+			lightThemeId,
 			darkMode,
 			syncDeviceDarkMode,
 			themesCount,
diff --git a/src/client/pages/theme-editor.vue b/src/client/pages/theme-editor.vue
index 8d0ba3e18c..0558451e2c 100644
--- a/src/client/pages/theme-editor.vue
+++ b/src/client/pages/theme-editor.vue
@@ -221,9 +221,9 @@ export default defineComponent({
 			addTheme(this.theme);
 			applyTheme(this.theme);
 			if (this.$store.state.darkMode) {
-				ColdDeviceStorage.set('darkTheme', this.theme.id);
+				ColdDeviceStorage.set('darkTheme', this.theme);
 			} else {
-				ColdDeviceStorage.set('lightTheme', this.theme.id);
+				ColdDeviceStorage.set('lightTheme', this.theme);
 			}
 			this.changed = false;
 			os.dialog({
diff --git a/src/client/scripts/theme.ts b/src/client/scripts/theme.ts
index f3719a23d8..b0bf620a7d 100644
--- a/src/client/scripts/theme.ts
+++ b/src/client/scripts/theme.ts
@@ -9,19 +9,19 @@ export type Theme = {
 	props: Record<string, string>;
 };
 
-export const lightTheme: Theme = require('../themes/_light.json5');
-export const darkTheme: Theme = require('../themes/_dark.json5');
+export const lightTheme: Theme = require('@client/themes/_light.json5');
+export const darkTheme: Theme = require('@client/themes/_dark.json5');
 
 export const themeProps = Object.keys(lightTheme.props).filter(key => !key.startsWith('X'));
 
 export const builtinThemes = [
-	require('../themes/l-light.json5'),
-	require('../themes/l-apricot.json5'),
-	require('../themes/l-rainy.json5'),
+	require('@client/themes/l-light.json5'),
+	require('@client/themes/l-apricot.json5'),
+	require('@client/themes/l-rainy.json5'),
 
-	require('../themes/d-dark.json5'),
-	require('../themes/d-persimmon.json5'),
-	require('../themes/d-black.json5'),
+	require('@client/themes/d-dark.json5'),
+	require('@client/themes/d-persimmon.json5'),
+	require('@client/themes/d-black.json5'),
 ] as Theme[];
 
 let timeout = null;
diff --git a/src/client/store.ts b/src/client/store.ts
index bccb6cc206..cdc244537f 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -212,10 +212,8 @@ type Plugin = {
  */
 export class ColdDeviceStorage {
 	public static default = {
-		// TODO: テーマをアカウントに保存するようになったのにもかかわらず、以下のどのテーマを使うかという情報だけがブラウザ保存になっていて、アカウント切り替えたりログアウトしたときに不具合が発生するのでなんとかする
-		// テーマIDを保存するのではなく、テーマ自体を保存するようにすれば解決するかも
-		darkTheme: '8050783a-7f63-445a-b270-36d0f6ba1677',
-		lightTheme: '4eea646f-7afa-4645-83e9-83af0333cd37',
+		lightTheme: require('@client/themes/l-light.json5') as Theme,
+		darkTheme: require('@client/themes/d-dark.json5') as Theme,
 		syncDeviceDarkMode: true,
 		chatOpenBehavior: 'page' as 'page' | 'window' | 'popout',
 		plugins: [] as Plugin[],
diff --git a/src/client/theme-store.ts b/src/client/theme-store.ts
index 3793debb9e..f291069692 100644
--- a/src/client/theme-store.ts
+++ b/src/client/theme-store.ts
@@ -1,6 +1,5 @@
 import { api } from '@client/os';
 import { $i } from '@client/account';
-import { ColdDeviceStorage } from './store';
 import { Theme } from './scripts/theme';
 
 const lsCacheKey = $i ? `themes:${$i.id}` : '';