This commit is contained in:
syuilo 2021-04-12 22:07:32 +09:00
parent 7b1c113c29
commit dabe131234
6 changed files with 69 additions and 44 deletions

View file

@ -6,7 +6,7 @@ import '@client/style.scss';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing'; import { Integrations } from '@sentry/tracing';
import { createApp, watch } from 'vue'; import { computed, createApp, watch } from 'vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import widgets from '@client/widgets'; import widgets from '@client/widgets';
@ -25,7 +25,6 @@ import { fetchInstance, instance } from '@client/instance';
import { makeHotkey } from '@client/scripts/hotkey'; import { makeHotkey } from '@client/scripts/hotkey';
import { search } from '@client/scripts/search'; import { search } from '@client/scripts/search';
import { isMobile } from '@client/scripts/is-mobile'; import { isMobile } from '@client/scripts/is-mobile';
import { getThemes } from '@client/theme-store';
import { initializeSw } from '@client/scripts/initialize-sw'; import { initializeSw } from '@client/scripts/initialize-sw';
import { reloadChannel } from '@client/scripts/unison-reload'; import { reloadChannel } from '@client/scripts/unison-reload';
import { reactionPicker } from '@client/scripts/reaction-picker'; import { reactionPicker } from '@client/scripts/reaction-picker';
@ -36,6 +35,13 @@ console.info(`Misskey v${version}`);
window.onerror = null; window.onerror = null;
window.onunhandledrejection = 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_) { if (_DEV_) {
console.warn('Development mode!!!'); console.warn('Development mode!!!');
@ -205,12 +211,24 @@ if (splash) {
} }
watch(defaultStore.reactiveState.darkMode, (darkMode) => { watch(defaultStore.reactiveState.darkMode, (darkMode) => {
import('@client/scripts/theme').then(({ builtinThemes }) => { applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
const themes = builtinThemes.concat(getThemes());
applyTheme(themes.find(x => x.id === (darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'))));
});
}, { immediate: localStorage.theme == null }); }, { 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 //#region Sync dark mode
if (ColdDeviceStorage.get('syncDeviceDarkMode')) { if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', isDeviceDarkmode()); defaultStore.set('darkMode', isDeviceDarkmode());

View file

@ -27,7 +27,7 @@
</FormGroup> </FormGroup>
<template v-if="darkMode"> <template v-if="darkMode">
<FormSelect v-model:value="darkTheme"> <FormSelect v-model:value="darkThemeId">
<template #label>{{ $ts.themeForDarkMode }}</template> <template #label>{{ $ts.themeForDarkMode }}</template>
<optgroup :label="$ts.darkThemes"> <optgroup :label="$ts.darkThemes">
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option> <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> <option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup> </optgroup>
</FormSelect> </FormSelect>
<FormSelect v-model:value="lightTheme"> <FormSelect v-model:value="lightThemeId">
<template #label>{{ $ts.themeForLightMode }}</template> <template #label>{{ $ts.themeForLightMode }}</template>
<optgroup :label="$ts.lightThemes"> <optgroup :label="$ts.lightThemes">
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option> <option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@ -47,7 +47,7 @@
</FormSelect> </FormSelect>
</template> </template>
<template v-else> <template v-else>
<FormSelect v-model:value="lightTheme"> <FormSelect v-model:value="lightThemeId">
<template #label>{{ $ts.themeForLightMode }}</template> <template #label>{{ $ts.themeForLightMode }}</template>
<optgroup :label="$ts.lightThemes"> <optgroup :label="$ts.lightThemes">
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option> <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> <option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup> </optgroup>
</FormSelect> </FormSelect>
<FormSelect v-model:value="darkTheme"> <FormSelect v-model:value="darkThemeId">
<template #label>{{ $ts.themeForDarkMode }}</template> <template #label>{{ $ts.themeForDarkMode }}</template>
<optgroup :label="$ts.darkThemes"> <optgroup :label="$ts.darkThemes">
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option> <option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@ -77,7 +77,7 @@
<FormGroup> <FormGroup>
<FormLink to="/theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }}</FormLink> <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> </FormGroup>
<FormLink to="/settings/theme/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink> <FormLink to="/settings/theme/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink>
@ -85,7 +85,7 @@
</template> </template>
<script lang="ts"> <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 { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye, faGlobe, faPaintRoller } from '@fortawesome/free-solid-svg-icons';
import FormSwitch from '@client/components/form/switch.vue'; import FormSwitch from '@client/components/form/switch.vue';
import FormSelect from '@client/components/form/select.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 FormGroup from '@client/components/form/group.vue';
import FormLink from '@client/components/form/link.vue'; import FormLink from '@client/components/form/link.vue';
import FormButton from '@client/components/form/button.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 { selectFile } from '@client/scripts/select-file';
import { isDeviceDarkmode } from '@client/scripts/is-device-darkmode'; import { isDeviceDarkmode } from '@client/scripts/is-device-darkmode';
import { ColdDeviceStorage } from '@client/store'; import { ColdDeviceStorage } from '@client/store';
@ -124,25 +124,29 @@ export default defineComponent({
const themes = computed(() => builtinThemes.concat(installedThemes.value)); const themes = computed(() => builtinThemes.concat(installedThemes.value));
const darkThemes = computed(() => themes.value.filter(t => t.base == 'dark' || t.kind == 'dark')); 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 lightThemes = computed(() => themes.value.filter(t => t.base == 'light' || t.kind == 'light'));
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); const darkTheme = ColdDeviceStorage.ref('darkTheme');
const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); 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 darkMode = computed(defaultStore.makeGetterSetter('darkMode'));
const syncDeviceDarkMode = computed(ColdDeviceStorage.makeGetterSetter('syncDeviceDarkMode')); const syncDeviceDarkMode = computed(ColdDeviceStorage.makeGetterSetter('syncDeviceDarkMode'));
const wallpaper = ref(localStorage.getItem('wallpaper')); const wallpaper = ref(localStorage.getItem('wallpaper'));
const themesCount = installedThemes.value.length; 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, () => { watch(syncDeviceDarkMode, () => {
if (syncDeviceDarkMode) { if (syncDeviceDarkMode) {
defaultStore.set('darkMode', isDeviceDarkmode()); defaultStore.set('darkMode', isDeviceDarkmode());
@ -162,6 +166,12 @@ export default defineComponent({
emit('info', INFO); emit('info', INFO);
}); });
onActivated(() => {
fetchThemes().then(() => {
installedThemes.value = getThemes();
});
});
fetchThemes().then(() => { fetchThemes().then(() => {
installedThemes.value = getThemes(); installedThemes.value = getThemes();
}); });
@ -170,8 +180,8 @@ export default defineComponent({
[symbols.PAGE_INFO]: INFO, [symbols.PAGE_INFO]: INFO,
darkThemes, darkThemes,
lightThemes, lightThemes,
darkTheme, darkThemeId,
lightTheme, lightThemeId,
darkMode, darkMode,
syncDeviceDarkMode, syncDeviceDarkMode,
themesCount, themesCount,

View file

@ -221,9 +221,9 @@ export default defineComponent({
addTheme(this.theme); addTheme(this.theme);
applyTheme(this.theme); applyTheme(this.theme);
if (this.$store.state.darkMode) { if (this.$store.state.darkMode) {
ColdDeviceStorage.set('darkTheme', this.theme.id); ColdDeviceStorage.set('darkTheme', this.theme);
} else { } else {
ColdDeviceStorage.set('lightTheme', this.theme.id); ColdDeviceStorage.set('lightTheme', this.theme);
} }
this.changed = false; this.changed = false;
os.dialog({ os.dialog({

View file

@ -9,19 +9,19 @@ export type Theme = {
props: Record<string, string>; props: Record<string, string>;
}; };
export const lightTheme: Theme = require('../themes/_light.json5'); export const lightTheme: Theme = require('@client/themes/_light.json5');
export const darkTheme: Theme = require('../themes/_dark.json5'); export const darkTheme: Theme = require('@client/themes/_dark.json5');
export const themeProps = Object.keys(lightTheme.props).filter(key => !key.startsWith('X')); export const themeProps = Object.keys(lightTheme.props).filter(key => !key.startsWith('X'));
export const builtinThemes = [ export const builtinThemes = [
require('../themes/l-light.json5'), require('@client/themes/l-light.json5'),
require('../themes/l-apricot.json5'), require('@client/themes/l-apricot.json5'),
require('../themes/l-rainy.json5'), require('@client/themes/l-rainy.json5'),
require('../themes/d-dark.json5'), require('@client/themes/d-dark.json5'),
require('../themes/d-persimmon.json5'), require('@client/themes/d-persimmon.json5'),
require('../themes/d-black.json5'), require('@client/themes/d-black.json5'),
] as Theme[]; ] as Theme[];
let timeout = null; let timeout = null;

View file

@ -212,10 +212,8 @@ type Plugin = {
*/ */
export class ColdDeviceStorage { export class ColdDeviceStorage {
public static default = { public static default = {
// TODO: テーマをアカウントに保存するようになったのにもかかわらず、以下のどのテーマを使うかという情報だけがブラウザ保存になっていて、アカウント切り替えたりログアウトしたときに不具合が発生するのでなんとかする lightTheme: require('@client/themes/l-light.json5') as Theme,
// テーマIDを保存するのではなく、テーマ自体を保存するようにすれば解決するかも darkTheme: require('@client/themes/d-dark.json5') as Theme,
darkTheme: '8050783a-7f63-445a-b270-36d0f6ba1677',
lightTheme: '4eea646f-7afa-4645-83e9-83af0333cd37',
syncDeviceDarkMode: true, syncDeviceDarkMode: true,
chatOpenBehavior: 'page' as 'page' | 'window' | 'popout', chatOpenBehavior: 'page' as 'page' | 'window' | 'popout',
plugins: [] as Plugin[], plugins: [] as Plugin[],

View file

@ -1,6 +1,5 @@
import { api } from '@client/os'; import { api } from '@client/os';
import { $i } from '@client/account'; import { $i } from '@client/account';
import { ColdDeviceStorage } from './store';
import { Theme } from './scripts/theme'; import { Theme } from './scripts/theme';
const lsCacheKey = $i ? `themes:${$i.id}` : ''; const lsCacheKey = $i ? `themes:${$i.id}` : '';