summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-06-07 20:24:44 -0400
committerHazelnoot <acomputerdog@gmail.com>2025-06-07 20:24:44 -0400
commit4085c8a4f14d94c6a2136575d4b9041921f7875d (patch)
treeb6b69acb0f7aed4e52a97cd537d95a2c2f41ca33 /packages/frontend/src
parentfix response type of i/registry/get endpoint (diff)
downloadsharkey-4085c8a4f14d94c6a2136575d4b9041921f7875d.tar.gz
sharkey-4085c8a4f14d94c6a2136575d4b9041921f7875d.tar.bz2
sharkey-4085c8a4f14d94c6a2136575d4b9041921f7875d.zip
integrate localStorage options into preference system
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/pages/settings/custom-css.vue18
-rw-r--r--packages/frontend/src/pages/settings/preferences.vue66
-rw-r--r--packages/frontend/src/pref-migrate.ts11
-rw-r--r--packages/frontend/src/preferences/def.ts83
-rw-r--r--packages/frontend/src/preferences/manager.ts40
5 files changed, 118 insertions, 100 deletions
diff --git a/packages/frontend/src/pages/settings/custom-css.vue b/packages/frontend/src/pages/settings/custom-css.vue
index 07b16d5c45..5b9b0d897a 100644
--- a/packages/frontend/src/pages/settings/custom-css.vue
+++ b/packages/frontend/src/pages/settings/custom-css.vue
@@ -23,24 +23,8 @@ import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { miLocalStorage } from '@/local-storage.js';
import { prefer } from '@/preferences.js';
-import { reloadAsk } from '@/utility/reload-ask';
-const customCssModel = prefer.model('customCss');
-const localCustomCss = computed<string>({
- get() {
- return customCssModel.value ?? miLocalStorage.getItem('customCss') ?? '';
- },
- set(newCustomCss) {
- customCssModel.value = newCustomCss;
- if (newCustomCss) {
- miLocalStorage.setItem('customCss', newCustomCss);
- } else {
- miLocalStorage.removeItem('customCss');
- }
-
- reloadAsk(true);
- },
-});
+const localCustomCss = prefer.model('customCss');
const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
index ed0e3689a5..84c625b502 100644
--- a/packages/frontend/src/pages/settings/preferences.vue
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -1059,68 +1059,13 @@ const clickToOpen = prefer.model('clickToOpen');
const useCustomSearchEngine = computed(() => !Object.keys(searchEngineMap).includes(searchEngine.value));
const defaultCW = ref($i.defaultCW);
const defaultCWPriority = ref($i.defaultCWPriority);
-
-const langModel = prefer.model('lang');
-const lang = computed<string>({
- get() {
- return langModel.value ?? miLocalStorage.getItem('lang') ?? 'en-US';
- },
- set(newLang) {
- langModel.value = newLang;
- miLocalStorage.setItem('lang', newLang);
- miLocalStorage.removeItem('locale');
- miLocalStorage.removeItem('localeVersion');
- },
-});
-
-const fontSizeModel = prefer.model('fontSize');
-const fontSize = computed<'0' | '1' | '2' | '3'>({
- get() {
- return fontSizeModel.value ?? miLocalStorage.getItem('fontSize') ?? '0';
- },
- set(newFontSize) {
- fontSizeModel.value = newFontSize;
- if (newFontSize !== '0') {
- miLocalStorage.setItem('fontSize', newFontSize);
- } else {
- miLocalStorage.removeItem('fontSize');
- }
- },
-});
-
-const useSystemFontModel = prefer.model('useSystemFont');
-const useSystemFont = computed<boolean>({
- get() {
- return useSystemFontModel.value ?? (miLocalStorage.getItem('useSystemFont') != null);
- },
- set(newUseSystemFont) {
- useSystemFontModel.value = newUseSystemFont;
- if (newUseSystemFont) {
- miLocalStorage.setItem('useSystemFont', 't');
- } else {
- miLocalStorage.removeItem('useSystemFont');
- }
- },
-});
-
-const cornerRadiusModel = prefer.model('cornerRadius');
-const cornerRadius = computed<'misskey' | 'sharkey'>({
- get() {
- return cornerRadiusModel.value ?? miLocalStorage.getItem('cornerRadius') ?? 'sharkey';
- },
- set(newCornerRadius) {
- cornerRadiusModel.value = newCornerRadius;
- if (newCornerRadius === 'sharkey') {
- miLocalStorage.removeItem('cornerRadius');
- } else {
- miLocalStorage.setItem('cornerRadius', newCornerRadius);
- }
- },
-});
+const lang = prefer.model('lang');
+const fontSize = prefer.model('fontSize');
+const useSystemFont = prefer.model('useSystemFont');
+const cornerRadius = prefer.model('cornerRadius');
watch([
hemisphere,
- lang,
enableInfiniteScroll,
showNoteActionsOnlyHover,
overridedDeviceKind,
@@ -1142,9 +1087,6 @@ watch([
useStickyIcons,
keepScreenOn,
contextMenu,
- fontSize,
- useSystemFont,
- cornerRadius,
makeEveryTextElementsSelectable,
noteDesign,
], async () => {
diff --git a/packages/frontend/src/pref-migrate.ts b/packages/frontend/src/pref-migrate.ts
index a7bb82a5f0..3250e7f1bd 100644
--- a/packages/frontend/src/pref-migrate.ts
+++ b/packages/frontend/src/pref-migrate.ts
@@ -13,6 +13,7 @@ import { deckStore } from '@/ui/deck/deck-store.js';
import { unisonReload } from '@/utility/unison-reload.js';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
+import { miLocalStorage } from '@/local-storage';
// TODO: そのうち消す
export function migrateOldSettings() {
@@ -167,5 +168,15 @@ export function migrateOldSettings() {
window.setTimeout(() => {
unisonReload();
}, 10000);
+ //#region Hybrid migrations
+ prefer.commit('fontSize', miLocalStorage.getItem('fontSize') ?? '0');
+ prefer.commit('useSystemFont', miLocalStorage.getItem('useSystemFont') != null);
+ prefer.commit('cornerRadius', miLocalStorage.getItem('cornerRadius') ?? 'sharkey');
+ prefer.commit('lang', miLocalStorage.getItem('lang') ?? 'en-US');
+ prefer.commit('customCss', miLocalStorage.getItem('customCss') ?? '');
+ prefer.commit('neverShowDonationInfo', miLocalStorage.getItem('neverShowDonationInfo') != null);
+ prefer.commit('neverShowLocalOnlyInfo', miLocalStorage.getItem('neverShowLocalOnlyInfo') != null);
+ //#endregion
+
});
}
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index fb795b1b7a..f430c4573c 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -10,11 +10,12 @@ import type { SoundType } from '@/utility/sound.js';
import type { Plugin } from '@/plugin.js';
import type { DeviceKind } from '@/utility/device-kind.js';
import type { DeckProfile } from '@/deck.js';
-import type { PreferencesDefinition } from './manager.js';
+import type { Pref, PreferencesDefinition } from './manager.js';
import type { FollowingFeedState } from '@/types/following-feed.js';
import { DEFAULT_DEVICE_KIND } from '@/utility/device-kind.js';
import { searchEngineMap } from '@/utility/search-engine-map.js';
import { defaultFollowingFeedState } from '@/types/following-feed.js';
+import { miLocalStorage } from '@/local-storage';
/** サウンド設定 */
export type SoundStore = {
@@ -484,25 +485,77 @@ export const PREF_DEF = {
// Null means "fall back to existing value from localStorage"
// For all of these preferences, "null" means fall back to existing value in localStorage.
fontSize: {
- default: null as null | '0' | '1' | '2' | '3',
- },
+ default: '0',
+ needsReload: true,
+ onSet: fontSize => {
+ if (fontSize !== '0') {
+ miLocalStorage.setItem('fontSize', fontSize);
+ } else {
+ miLocalStorage.removeItem('fontSize');
+ }
+ },
+ } as Pref<'0' | '1' | '2' | '3'>,
useSystemFont: {
- default: null as null | boolean,
- },
+ default: false,
+ needsReload: true,
+ onSet: useSystemFont => {
+ if (useSystemFont) {
+ miLocalStorage.setItem('useSystemFont', 't');
+ } else {
+ miLocalStorage.removeItem('useSystemFont');
+ }
+ },
+ } as Pref<boolean>,
cornerRadius: {
- default: null as null | 'misskey' | 'sharkey',
- },
+ default: 'sharkey',
+ needsReload: true,
+ onSet: cornerRadius => {
+ if (cornerRadius === 'sharkey') {
+ miLocalStorage.removeItem('cornerRadius');
+ } else {
+ miLocalStorage.setItem('cornerRadius', cornerRadius);
+ }
+ },
+ } as Pref<'misskey' | 'sharkey'>,
lang: {
- default: null as null | string,
- },
+ default: 'en-US',
+ needsReload: true,
+ onSet: lang => {
+ miLocalStorage.setItem('lang', lang);
+ miLocalStorage.removeItem('locale');
+ miLocalStorage.removeItem('localeVersion');
+ },
+ } as Pref<string>,
customCss: {
- default: null as null | string,
- },
+ default: '',
+ needsReload: true,
+ onSet: customCss => {
+ if (customCss) {
+ miLocalStorage.setItem('customCss', customCss);
+ } else {
+ miLocalStorage.removeItem('customCss');
+ }
+ },
+ } as Pref<string>,
neverShowDonationInfo: {
- default: null as null | 'true',
- },
+ default: false,
+ onSet: neverShowDonationInfo => {
+ if (neverShowDonationInfo) {
+ miLocalStorage.setItem('neverShowDonationInfo', 'true');
+ } else {
+ miLocalStorage.removeItem('neverShowDonationInfo');
+ }
+ },
+ } as Pref<boolean>,
neverShowLocalOnlyInfo: {
- default: null as null | 'true',
- },
+ default: false,
+ onSet: neverShowLocalOnlyInfo => {
+ if (neverShowLocalOnlyInfo) {
+ miLocalStorage.setItem('neverShowLocalOnlyInfo', 'true');
+ } else {
+ miLocalStorage.removeItem('neverShowLocalOnlyInfo');
+ }
+ },
+ } as Pref<boolean>,
//#endregion
} satisfies PreferencesDefinition;
diff --git a/packages/frontend/src/preferences/manager.ts b/packages/frontend/src/preferences/manager.ts
index f96aa2f368..b57a8d2b2a 100644
--- a/packages/frontend/src/preferences/manager.ts
+++ b/packages/frontend/src/preferences/manager.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { computed, onUnmounted, ref, watch } from 'vue';
+import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
import { v4 as uuid } from 'uuid';
import { host, version } from '@@/js/config.js';
import { PREF_DEF } from './def.js';
@@ -14,6 +14,7 @@ import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { deepEqual } from '@/utility/deep-equal.js';
+import { reloadAsk } from '@/utility/reload-ask';
// NOTE: 明示的な設定値のひとつとして null もあり得るため、設定が存在しないかどうかを判定する目的で null で比較したり ?? を使ってはいけない
@@ -84,16 +85,29 @@ export type StorageProvider = {
cloudSet: <K extends keyof PREF>(ctx: { key: K; scope: Scope; value: ValueOf<K>; }) => Promise<void>;
};
-export type PreferencesDefinition = Record<string, {
- default: any;
+export type Pref<T> = {
+ default: T;
accountDependent?: boolean;
serverDependent?: boolean;
-}>;
+ needsReload?: boolean;
+ onSet?: (value: T) => void;
+};
+
+export type PreferencesDefinition = Record<string, Pref<any> | undefined>;
export class PreferencesManager {
private storageProvider: StorageProvider;
public profile: PreferencesProfile;
public cloudReady: Promise<void>;
+ private enableReload = true;
+
+ public suppressReload() {
+ this.enableReload = false;
+ }
+
+ public allowReload() {
+ this.enableReload = true;
+ }
/**
* static / state の略 (static が予約語のため)
@@ -126,11 +140,11 @@ export class PreferencesManager {
}
private isAccountDependentKey<K extends keyof PREF>(key: K): boolean {
- return (PREF_DEF as PreferencesDefinition)[key].accountDependent === true;
+ return (PREF_DEF as PreferencesDefinition)[key]?.accountDependent === true;
}
private isServerDependentKey<K extends keyof PREF>(key: K): boolean {
- return (PREF_DEF as PreferencesDefinition)[key].serverDependent === true;
+ return (PREF_DEF as PreferencesDefinition)[key]?.serverDependent === true;
}
private rewriteRawState<K extends keyof PREF>(key: K, value: ValueOf<K>) {
@@ -150,6 +164,20 @@ export class PreferencesManager {
this.rewriteRawState(key, v);
+ const pref = (PREF_DEF as PreferencesDefinition)[key];
+ if (pref) {
+ // Call custom setter
+ if (pref.onSet) {
+ pref.onSet(v);
+ }
+
+ // Prompt to reload the frontend
+ if (pref.needsReload && this.enableReload) {
+ // noinspection JSIgnoredPromiseFromCall
+ nextTick(() => reloadAsk({ unison: true }));
+ }
+ }
+
const record = this.getMatchedRecordOf(key);
if (parseScope(record[0]).account == null && this.isAccountDependentKey(key)) {