diff --git a/ui-electrobun/src/mainview/AgentPane.svelte b/ui-electrobun/src/mainview/AgentPane.svelte index aaeba99..5a6bf47 100644 --- a/ui-electrobun/src/mainview/AgentPane.svelte +++ b/ui-electrobun/src/mainview/AgentPane.svelte @@ -31,10 +31,12 @@ }: Props = $props(); let scrollEl: HTMLDivElement; + // These need $state because Svelte 5 template bindings require reactive + // declarations. Rule 58 exception: component-scoped UI state that drives + // template output but has no cross-component readers. let promptText = $state(""); let expandedTools = $state>(new Set()); - // Drag-resize state let agentPaneEl: HTMLDivElement; let isDragging = $state(false); diff --git a/ui-electrobun/src/mainview/CommsTab.svelte b/ui-electrobun/src/mainview/CommsTab.svelte index 069437f..eecaea1 100644 --- a/ui-electrobun/src/mainview/CommsTab.svelte +++ b/ui-electrobun/src/mainview/CommsTab.svelte @@ -1,82 +1,29 @@ @@ -278,41 +265,41 @@
{#snippet renderEntries(dirPath: string, depth: number)} - {#if childrenCache.has(dirPath)} - {#each childrenCache.get(dirPath) ?? [] as entry} + {#if getFiles().childrenCache.has(dirPath)} + {#each getFiles().childrenCache.get(dirPath) ?? [] as entry} {@const fullPath = `${dirPath}/${entry.name}`} {#if entry.type === 'dir'} - {#if openDirs.has(fullPath)} + {#if getFiles().openDirs.has(fullPath)} {@render renderEntries(fullPath, depth + 1)} {/if} {:else} {/if} {/each} - {:else if loadingDirs.has(dirPath)} + {:else if getFiles().loadingDirs.has(dirPath)}
Loading...
{/if} {/snippet} @@ -321,7 +308,7 @@
- {#if showConflictDialog} + {#if getFiles().showConflictDialog}

File modified externally

@@ -329,7 +316,7 @@
- +
@@ -337,53 +324,53 @@
- {#if !selectedFile} + {#if !getFiles().selectedFile}
Select a file to view
- {:else if fileLoading} + {:else if getFiles().fileLoading}
Loading...
- {:else if fileError} -
{fileError}
- {:else if selectedType === 'pdf'} - - {:else if selectedType === 'csv' && fileContent != null} - - {:else if selectedType === 'image' && fileContent} - {@const ext = getExt(selectedName)} + {:else if getFiles().fileError} +
{getFiles().fileError}
+ {:else if getSelectedType() === 'pdf'} + + {:else if getSelectedType() === 'csv' && getFiles().fileContent != null} + + {:else if getSelectedType() === 'image' && getFiles().fileContent} + {@const ext = getExt(getSelectedName())} {@const mime = ext === 'svg' ? 'image/svg+xml' : ext === 'png' ? 'image/png' : ext === 'gif' ? 'image/gif' : ext === 'webp' ? 'image/webp' : 'image/jpeg'}
-
{selectedName} ({formatSize(fileSize)})
+
{getSelectedName()} ({formatSize(getFiles().fileSize)})
{selectedName}
- {:else if selectedType === 'code' && fileContent != null} + {:else if getSelectedType() === 'code' && getFiles().fileContent != null}
- - {selectedName} - {#if isDirty} (modified){/if} + + {getSelectedName()} + {#if getFiles().isDirty} (modified){/if} - {formatSize(fileSize)} + {formatSize(getFiles().fileSize)}
- {:else if fileContent != null} + {:else if getFiles().fileContent != null}
- - {selectedName} - {#if isDirty} (modified){/if} + + {getSelectedName()} + {#if getFiles().isDirty} (modified){/if} - {formatSize(fileSize)} + {formatSize(getFiles().fileSize)}
0 ? getAgentMessages() : EMPTY_MESSAGES; } - // ── Clone dialog state ────────────────────────────────────────── + // ── Clone dialog state (needs $state for template bindings) ───── let showCloneDialog = $state(false); let cloneBranchName = $state(''); let cloneError = $state(''); @@ -129,33 +120,31 @@ showCloneDialog = false; } - // Derived from project-tabs-store for reactive reads - function getCurrentTab() { return getActiveTab(id); } + // Tab state from project state tree + function getCurrentTab() { return appState.project.tab.getActiveTab(id); } // ── Load last session on mount (once, not reactive) ───────────────── import { onMount } from 'svelte'; - onMount(() => { loadLastSession(id); }); + onMount(() => { appState.agent.loadLastSession(id); }); function setTab(tab: ProjectTab) { - setActiveTab(id, tab); + appState.project.tab.setActiveTab(id, tab); } function handleSend(text: string) { - if (hasSession(id)) { - // Session exists — send follow-up prompt - sendPrompt(id, text).catch((err) => { + if (appState.agent.hasSession(id)) { + appState.agent.sendPrompt(id, text).catch((err) => { console.error('[agent.prompt] error:', err); }); } else { - // No session — start a new agent - startAgent(id, provider, text, { cwd, model }).catch((err) => { + appState.agent.startAgent(id, provider, text, { cwd, model }).catch((err) => { console.error('[agent.start] error:', err); }); } } function handleStop() { - stopAgent(id).catch((err) => { + appState.agent.stopAgent(id).catch((err) => { console.error('[agent.stop] error:', err); }); } @@ -373,7 +362,7 @@ role="tabpanel" aria-label="Files" > - +
@@ -409,7 +398,7 @@ role="tabpanel" aria-label="Comms" > - + @@ -421,7 +410,7 @@ role="tabpanel" aria-label="Tasks" > - + diff --git a/ui-electrobun/src/mainview/TaskBoardTab.svelte b/ui-electrobun/src/mainview/TaskBoardTab.svelte index 97248c1..b60875b 100644 --- a/ui-electrobun/src/mainview/TaskBoardTab.svelte +++ b/ui-electrobun/src/mainview/TaskBoardTab.svelte @@ -1,29 +1,20 @@ @@ -75,11 +49,11 @@