|
1 | 1 | import { create } from 'zustand'; |
2 | 2 | import { immer } from 'zustand/middleware/immer'; |
3 | 3 | import { INITIAL_Z_INDEX, WINDOW_CONFIG } from '#constants'; |
4 | | - |
5 | | -/** * 1. THE BLUEPRINTS (Interfaces) |
6 | | - * Think of these as the "Rules of the House." |
7 | | - * They tell TypeScript exactly what a Window looks like. |
8 | | - */ |
9 | | -interface WindowState { |
10 | | - isOpen: boolean; |
11 | | - zIndex: number; |
12 | | - data: unknown; // Changed from null to any/unknown so it can actually hold data |
13 | | -} |
14 | | - |
15 | | -// WindowKey creates a list of allowed names (e.g., 'terminal' | 'browser') |
16 | | -// based on your actual config file (constants/index.ts). |
17 | | -export type WindowKey = keyof typeof WINDOW_CONFIG; |
| 4 | +import { WindowID, WindowState, FinderItem } from '#types'; |
18 | 5 |
|
19 | 6 | interface WindowStore { |
20 | | - windows: Record<WindowKey, WindowState>; // A map of all windows |
21 | | - nextZIndex: number; // The "depth" for the next focused window |
22 | | - openWindow: (windowKey: WindowKey, data?: unknown) => void; |
23 | | - closeWindow: (windowKey: WindowKey) => void; |
24 | | - focusWindow: (windowKey: WindowKey) => void; |
| 7 | + windows: Record<WindowID, WindowState>; |
| 8 | + nextZIndex: number; |
| 9 | + openWindow: (windowKey: WindowID, data?: FinderItem) => void; |
| 10 | + closeWindow: (windowKey: WindowID) => void; |
| 11 | + focusWindow: (windowKey: WindowID) => void; |
25 | 12 | } |
26 | 13 |
|
27 | | -/** |
28 | | - * 2. THE STORE |
29 | | - * We use 'immer' middleware here. Normally, React state must be "immutable" |
30 | | - * (you can't change it, you have to replace it). |
31 | | - * Immer lets us write 'state.windows[key].isOpen = true' which is much easier to read! |
32 | | - */ |
33 | 14 | const useWindowStore = create<WindowStore>()( |
34 | 15 | immer((set) => ({ |
35 | | - // Initial Data |
36 | | - windows: WINDOW_CONFIG, |
| 16 | + // Initialize using the config from constants |
| 17 | + windows: WINDOW_CONFIG as Record<WindowID, WindowState>, |
37 | 18 | nextZIndex: INITIAL_Z_INDEX + 1, |
38 | 19 |
|
39 | | - // ACTION: Open a window |
40 | | - openWindow: (windowKey, data = null) => |
| 20 | + // Open a specific window and optionally pass file data (FinderItem) |
| 21 | + openWindow: (windowKey, data) => |
41 | 22 | set((state) => { |
42 | 23 | const win = state.windows[windowKey]; |
43 | 24 | if (!win) return; |
44 | 25 |
|
45 | 26 | win.isOpen = true; |
46 | | - win.zIndex = state.nextZIndex; // Put it on top |
47 | | - win.data = data ?? win.data; // Attach any extra info (like a file path) |
48 | | - state.nextZIndex++; // Prepare the next Z-Index for the next window |
| 27 | + win.zIndex = state.nextZIndex; |
| 28 | + // Save the file object (Nike Project.txt, etc) into the window's data slot |
| 29 | + if (data) { |
| 30 | + state.windows[windowKey].data = data as FinderItem; |
| 31 | + } |
| 32 | + state.nextZIndex++; |
49 | 33 | }), |
50 | 34 |
|
51 | | - // ACTION: Hide a window |
| 35 | + // Close window and wipe its local data to keep it clean for next use |
52 | 36 | closeWindow: (windowKey) => |
53 | 37 | set((state) => { |
54 | 38 | const win = state.windows[windowKey]; |
55 | 39 | if (!win) return; |
56 | 40 |
|
57 | 41 | win.isOpen = false; |
58 | | - win.zIndex = INITIAL_Z_INDEX; // Send it back to the bottom |
| 42 | + win.zIndex = INITIAL_Z_INDEX; |
59 | 43 | win.data = null; |
60 | 44 | }), |
61 | 45 |
|
62 | | - // ACTION: Click to focus |
| 46 | + // Bring window to front |
63 | 47 | focusWindow: (windowKey) => |
64 | 48 | set((state) => { |
65 | 49 | const win = state.windows[windowKey]; |
66 | 50 | if (!win) return; |
67 | 51 |
|
68 | | - // Every time you click, we give it a higher number than anyone else |
69 | 52 | win.zIndex = state.nextZIndex; |
70 | 53 | state.nextZIndex++; |
71 | 54 | }), |
|
0 commit comments