返回 DeepSeek-Reasonix
layoutPreferences.ts
根目录 / desktop / frontend / src / lib / layoutPreferences.ts
1 export type LayoutSizeKey =
2 | "sidebarWidth"
3 | "sidebarWidthGraphite"
4 | "rightDockWidth"
5 | "rightDockTreeWidth"
6 | "rightDockPreviewWidth"
7 | "workspaceFileTreePanelWidth"
8 | "workspaceTreeWidth"
9 | "composerHeight"
10 | "drawerWidth"
11 | "settingsDrawerWidth";
12
13 type LayoutPreferences = {
14 sizes?: Partial<Record<LayoutSizeKey, number>>;
15 };
16
17 const STORAGE_KEY = "reasonix.layoutPreferences.v1";
18
19 const LEGACY_SIZE_KEYS: Record<LayoutSizeKey, string[]> = {
20 sidebarWidth: ["reasonix.sidebar.width"],
21 sidebarWidthGraphite: [],
22 rightDockWidth: [],
23 rightDockTreeWidth: [],
24 rightDockPreviewWidth: [],
25 workspaceFileTreePanelWidth: [],
26 workspaceTreeWidth: ["reasonix.workspaceTree.width"],
27 composerHeight: ["reasonix.composerHeight"],
28 drawerWidth: ["reasonix.drawer.width"],
29 settingsDrawerWidth: ["reasonix.settingsDrawer.width"],
30 };
31
32 type ClampSize = (value: number) => number;
33
34 function readPrefs(): LayoutPreferences {
35 if (typeof window === "undefined") return {};
36 try {
37 const raw = window.localStorage.getItem(STORAGE_KEY);
38 if (!raw) return {};
39 const parsed = JSON.parse(raw) as LayoutPreferences;
40 return parsed && typeof parsed === "object" ? parsed : {};
41 } catch {
42 return {};
43 }
44 }
45
46 function writePrefs(prefs: LayoutPreferences): void {
47 if (typeof window === "undefined") return;
48 try {
49 window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ sizes: prefs.sizes ?? {} }));
50 } catch {
51 /* ignore storage failures */
52 }
53 }
54
55 function readLegacySize(key: LayoutSizeKey): number | null {
56 if (typeof window === "undefined") return null;
57 for (const legacyKey of LEGACY_SIZE_KEYS[key]) {
58 try {
59 const raw = Number(window.localStorage.getItem(legacyKey));
60 if (Number.isFinite(raw) && raw > 0) return raw;
61 } catch {
62 /* keep trying other keys */
63 }
64 }
65 return null;
66 }
67
68 function normalizeSize(value: number, clamp?: ClampSize): number {
69 const rounded = Math.round(value);
70 return clamp ? clamp(rounded) : rounded;
71 }
72
73 export function loadLayoutSize(key: LayoutSizeKey, fallback: number, clamp?: ClampSize): number {
74 const prefs = readPrefs();
75 const saved = prefs.sizes?.[key];
76 const value = Number.isFinite(saved) && saved! > 0 ? saved! : readLegacySize(key);
77 return value === null ? normalizeSize(fallback, clamp) : normalizeSize(value, clamp);
78 }
79
80 export function loadOptionalLayoutSize(key: LayoutSizeKey, clamp?: ClampSize): number | null {
81 const prefs = readPrefs();
82 const saved = prefs.sizes?.[key];
83 const value = Number.isFinite(saved) && saved! > 0 ? saved! : readLegacySize(key);
84 return value === null ? null : normalizeSize(value, clamp);
85 }
86
87 export function saveLayoutSize(key: LayoutSizeKey, value: number, clamp?: ClampSize): void {
88 const prefs = readPrefs();
89 const sizes = { ...(prefs.sizes ?? {}), [key]: normalizeSize(value, clamp) };
90 writePrefs({ ...prefs, sizes });
91 }
92
93 export function clearLayoutSize(key: LayoutSizeKey): void {
94 const prefs = readPrefs();
95 const sizes = { ...(prefs.sizes ?? {}) };
96 delete sizes[key];
97 writePrefs({ ...prefs, sizes });
98 }
99
99 lines TYPESCRIPT