M0-M11 狩夜人笔记初始实现:11里程碑+86测试

This commit is contained in:
hunter-dev
2026-08-24 20:35:22 +08:00
commit 3ebd33536b
106 changed files with 10490 additions and 0 deletions
@@ -0,0 +1,54 @@
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),
}));