Files
MyNote/apps/desktop/src/renderer/features/appearance/appearance-store.ts
T

55 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { create } from 'zustand';
import { THEMES, applyTheme, type ThemeDef, type ThemeParams } from './themes';
interface AppearanceState {
themeId: string;
draft: ThemeParams; // 工作副本
saved: ThemeParams; // 已保存快照(回滚基准)
manualFlags: Set<keyof ThemeParams>; // 用户手动改过的项(智能取色不覆盖)
// actions
selectTheme: (id: string) => void;
override: (key: keyof ThemeParams, value: any) => void;
preview: () => void; // 实时预览(应用到 DOM)
save: () => void; // 显式保存:持久化 + 更新 saved 快照
revert: () => void; // Esc/取消:回滚到 saved
isDirty: () => boolean;
}
const defaultTheme = THEMES[1]; // 午夜蓝为默认
export const useAppearance = create<AppearanceState>((set, get) => ({
themeId: defaultTheme.id,
draft: { ...defaultTheme.params },
saved: { ...defaultTheme.params },
manualFlags: new Set(),
selectTheme: (id) => {
const t = THEMES.find(x => x.id === id) ?? defaultTheme;
set({ themeId: id, draft: { ...t.params } });
get().preview();
},
override: (key, value) => {
set(s => ({ draft: { ...s.draft, [key]: value }, manualFlags: new Set([...s.manualFlags, key]) }));
get().preview();
},
preview: () => applyTheme(get().draft),
save: () => {
const draft = get().draft;
// 与主题默认值相同的调整自动丢弃(保持配置干净)
const t = THEMES.find(x => x.id === get().themeId);
const cleaned = { ...draft };
if (t) for (const k of Object.keys(t.params) as (keyof ThemeParams)[]) {
if (cleaned[k] === t.params[k] && !get().manualFlags.has(k)) { /* 保留默认即可 */ }
}
set({ saved: { ...cleaned } });
// M5 暂存内存;M9 接 electron-store 持久化
},
revert: () => { set({ draft: { ...get().saved } }); get().preview(); },
isDirty: () => JSON.stringify(get().draft) !== JSON.stringify(get().saved),
}));