adamelmore 1 месяц назад
Родитель
Сommit
962ab3bc8c
2 измененных файлов с 53 добавлено и 13 удалено
  1. 25 6
      packages/app/src/context/layout.tsx
  2. 28 7
      packages/app/src/pages/layout.tsx

+ 25 - 6
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)

+ 28 - 7
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))
       }),
     )