refactor(electrobun): centralize all shared state into global stores
New stores: - ui-store.svelte.ts: settingsOpen, paletteOpen, searchOpen, notifDrawerOpen, showWizard, settingsCategory, projectToDelete, showAddGroup, newGroupName - project-tabs-store.svelte.ts: per-project activeTab + activatedTabs via Map Wired: - App.svelte: 8 inline $state removed, reads/writes via ui-store - ProjectCard: activeTab/activatedTabs from project-tabs-store - SettingsDrawer: activeCategory from ui-store - CommandPalette: 4 commands call ui-store directly (no CustomEvent dispatch) Components are now pure view layers reading from stores.
This commit is contained in:
parent
c88577a34a
commit
2b1194c809
6 changed files with 230 additions and 60 deletions
67
ui-electrobun/src/mainview/project-tabs-store.svelte.ts
Normal file
67
ui-electrobun/src/mainview/project-tabs-store.svelte.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Project tabs store — per-project tab state.
|
||||
*
|
||||
* Tracks which tab is active and which tabs have been activated (PERSISTED-LAZY
|
||||
* pattern) for each project card. This allows cross-component access — e.g.,
|
||||
* StatusBar can show which tab is active, palette commands can switch tabs.
|
||||
*/
|
||||
|
||||
// ── Types ────────────────────────────────────────────────────────────────
|
||||
|
||||
export type ProjectTab =
|
||||
| 'model' | 'docs' | 'context' | 'files'
|
||||
| 'ssh' | 'memory' | 'comms' | 'tasks';
|
||||
|
||||
export const ALL_TABS: ProjectTab[] = [
|
||||
'model', 'docs', 'context', 'files', 'ssh', 'memory', 'comms', 'tasks',
|
||||
];
|
||||
|
||||
interface TabState {
|
||||
activeTab: ProjectTab;
|
||||
activatedTabs: Set<ProjectTab>;
|
||||
}
|
||||
|
||||
// ── State ────────────────────────────────────────────────────────────────
|
||||
|
||||
let _tabs = $state<Map<string, TabState>>(new Map());
|
||||
|
||||
// ── Internal helper ──────────────────────────────────────────────────────
|
||||
|
||||
function ensureEntry(projectId: string): TabState {
|
||||
let entry = _tabs.get(projectId);
|
||||
if (!entry) {
|
||||
entry = { activeTab: 'model', activatedTabs: new Set(['model']) };
|
||||
_tabs.set(projectId, entry);
|
||||
// Trigger reactivity by reassigning the map
|
||||
_tabs = new Map(_tabs);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
// ── Getters ──────────────────────────────────────────────────────────────
|
||||
|
||||
export function getActiveTab(projectId: string): ProjectTab {
|
||||
return _tabs.get(projectId)?.activeTab ?? 'model';
|
||||
}
|
||||
|
||||
export function isTabActivated(projectId: string, tab: ProjectTab): boolean {
|
||||
return _tabs.get(projectId)?.activatedTabs.has(tab) ?? (tab === 'model');
|
||||
}
|
||||
|
||||
// ── Actions ──────────────────────────────────────────────────────────────
|
||||
|
||||
export function setActiveTab(projectId: string, tab: ProjectTab): void {
|
||||
const entry = ensureEntry(projectId);
|
||||
entry.activeTab = tab;
|
||||
entry.activatedTabs = new Set([...entry.activatedTabs, tab]);
|
||||
// Trigger reactivity
|
||||
_tabs = new Map(_tabs);
|
||||
}
|
||||
|
||||
/** Remove tab state when a project is deleted. */
|
||||
export function removeProject(projectId: string): void {
|
||||
if (_tabs.has(projectId)) {
|
||||
_tabs.delete(projectId);
|
||||
_tabs = new Map(_tabs);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue