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.
67 lines
2.7 KiB
TypeScript
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);
|
|
}
|
|
}
|