diff options
| author | adamelmore <[email protected]> | 2026-01-24 00:35:02 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-24 07:00:41 -0600 |
| commit | 962ab3bc8cf0b051e9858db0c6c3e4b96a42bf1b (patch) | |
| tree | 3d147aebe8bb7e7c615e5fe96b49f90eb841393e /packages/app/src | |
| parent | da8f3e92a7bbc3b288f89f6b535b72b94c1d1c19 (diff) | |
| download | opencode-962ab3bc8cf0b051e9858db0c6c3e4b96a42bf1b.tar.gz opencode-962ab3bc8cf0b051e9858db0c6c3e4b96a42bf1b.zip | |
fix(app): reactive loops
Diffstat (limited to 'packages/app/src')
| -rw-r--r-- | packages/app/src/context/layout.tsx | 31 | ||||
| -rw-r--r-- | packages/app/src/pages/layout.tsx | 35 |
2 files changed, 53 insertions, 13 deletions
diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index ddd66aa2f..c24e433d1 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -267,17 +267,36 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( return map }) - createEffect(() => { + const rootFor = (directory: string) => { const map = roots() - if (map.size === 0) return + if (map.size === 0) return directory + + const visited = new Set<string>() + const chain = [directory] + + while (chain.length) { + const current = chain[chain.length - 1] + if (!current) return directory + const next = map.get(current) + if (!next) return current + + if (visited.has(next)) return directory + visited.add(next) + chain.push(next) + } + + return directory + } + + createEffect(() => { const projects = server.projects.list() const seen = new Set(projects.map((project) => project.worktree)) batch(() => { for (const project of projects) { - const root = map.get(project.worktree) - if (!root) continue + const root = rootFor(project.worktree) + if (root === project.worktree) continue server.projects.close(project.worktree) @@ -350,7 +369,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( projects: { list, open(directory: string) { - const root = roots().get(directory) ?? directory + const root = rootFor(directory) if (server.projects.list().find((x) => x.worktree === root)) return globalSync.project.loadSessions(root) server.projects.open(root) @@ -384,7 +403,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setStore("sidebar", "width", width) }, workspaces(directory: string) { - return createMemo(() => store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false) + return () => store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false }, setWorkspaces(directory: string, value: boolean) { setStore("sidebar", "workspaces", directory, value) diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 714e23b23..202996eea 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -724,7 +724,8 @@ export default function Layout(props: ParentProps) { if (!directory) return const [store] = globalSync.child(directory) - if (store.message[session.id] !== undefined) return + const cached = untrack(() => store.message[session.id] !== undefined) + if (cached) return const q = queueFor(directory) if (q.inflight.has(session.id)) return @@ -855,14 +856,34 @@ export default function Layout(props: ParentProps) { setStore( produce((draft) => { const removed = new Set<string>([session.id]) - const collect = (parentID: string) => { - for (const item of draft.session) { - if (item.parentID !== parentID) continue - removed.add(item.id) - collect(item.id) + + const byParent = new Map<string, string[]>() + for (const item of draft.session) { + const parentID = item.parentID + if (!parentID) continue + const existing = byParent.get(parentID) + if (existing) { + existing.push(item.id) + continue } + byParent.set(parentID, [item.id]) } - collect(session.id) + + const stack = [session.id] + while (stack.length) { + const parentID = stack.pop() + if (!parentID) continue + + const children = byParent.get(parentID) + if (!children) continue + + for (const child of children) { + if (removed.has(child)) continue + removed.add(child) + stack.push(child) + } + } + draft.session = draft.session.filter((s) => !removed.has(s.id)) }), ) |
