-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathappStore.ts
More file actions
124 lines (111 loc) · 3.45 KB
/
Copy pathappStore.ts
File metadata and controls
124 lines (111 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import { AppStore, AppState } from './types';
const initialState: AppState = {
spaces: [],
activeSpaceId: null,
viewSpaceId: null,
sidebarCollapsed: false,
theme: 'system',
analyticsEnabled: true,
loading: {
spaces: false,
servers: false,
},
};
export const useAppStore = create<AppStore>()(
persist(
immer((set) => ({
...initialState,
// Spaces
setSpaces: (spaces) =>
set((state) => {
state.spaces = spaces;
// Validate persisted activeSpaceId still exists, reset to default if not
const activeExists = state.activeSpaceId
? spaces.some((s) => s.id === state.activeSpaceId)
: false;
if (!activeExists && spaces.length > 0) {
const defaultSpace = spaces.find((s) => s.is_default);
state.activeSpaceId = defaultSpace?.id ?? spaces[0].id;
}
const viewExists = state.viewSpaceId
? spaces.some((s) => s.id === state.viewSpaceId)
: false;
if (!viewExists) {
state.viewSpaceId = state.activeSpaceId;
}
}),
setActiveSpace: (id) =>
set((state) => {
const shouldFollow = !state.viewSpaceId || state.viewSpaceId === state.activeSpaceId;
state.activeSpaceId = id;
if (shouldFollow) {
state.viewSpaceId = id;
}
}),
setViewSpace: (id) =>
set((state) => {
state.viewSpaceId = id;
}),
addSpace: (space) =>
set((state) => {
state.spaces.push(space);
if (space.is_default || state.spaces.length === 1) {
state.activeSpaceId = space.id;
}
if (!state.viewSpaceId) {
state.viewSpaceId = state.activeSpaceId;
}
}),
removeSpace: (id) =>
set((state) => {
state.spaces = state.spaces.filter((s) => s.id !== id);
if (state.activeSpaceId === id) {
state.activeSpaceId = state.spaces[0]?.id ?? null;
}
if (state.viewSpaceId === id) {
state.viewSpaceId = state.activeSpaceId;
}
}),
updateSpace: (id, updates) =>
set((state) => {
const index = state.spaces.findIndex((s) => s.id === id);
if (index !== -1) {
state.spaces[index] = { ...state.spaces[index], ...updates };
}
}),
// UI
toggleSidebar: () =>
set((state) => {
state.sidebarCollapsed = !state.sidebarCollapsed;
}),
setTheme: (theme) =>
set((state) => {
state.theme = theme;
}),
setAnalyticsEnabled: (enabled) =>
set((state) => {
state.analyticsEnabled = enabled;
}),
// Loading
setLoading: (key, value) =>
set((state) => {
state.loading[key] = value;
}),
})),
{
name: 'mcpmux-storage',
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({
// Only persist these fields
// Note: viewSpaceId is NOT persisted - always starts as activeSpaceId on launch
activeSpaceId: state.activeSpaceId,
sidebarCollapsed: state.sidebarCollapsed,
theme: state.theme,
analyticsEnabled: state.analyticsEnabled,
}),
}
)
);