agent-orchestrator/ui-electrobun/src/mainview/project-tabs-store.svelte.ts
Hibryda 2b1194c809 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.
2026-03-23 20:26:07 +01:00

67 lines
2.7 KiB
TypeScript

/**
* 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);
}
}