fix(host): review round 8 — unmount invalidation, unreadable selections clear

- HMR/unmount bumps both request generations, so a listing or creation
  settling after disposal neither updates dead state nor issues the
  post-create relist.
- A selection whose preview listing fails clears back to the single pane:
  the breadcrumb names the level, so the level must be the committing
  target (reverses the earlier keep-marked behavior with its test).
This commit is contained in:
creatixchu
2026-07-29 00:50:49 +08:00
parent 8ba0647c2c
commit cbf54196fa
2 changed files with 38 additions and 12 deletions

View File

@@ -124,6 +124,12 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
// text input; the same guard the workspace-name inputs carry, shared by
// the path editor and the folder-name input.
const composingRef = useRef(false)
// HMR/unmount invalidation: a completion from a disposed flow must not
// update state or issue follow-up requests from a dead component.
useEffect(() => () => {
requestSeq.current += 1
openGeneration.current += 1
}, [])
const compositionGuard = {
onCompositionStart: () => { composingRef.current = true },
onCompositionEnd: () => { composingRef.current = false },
@@ -163,6 +169,9 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
if (seq !== requestSeq.current) return
setLoading(false)
setError(failureText(reason))
// An unreadable selection cannot be the committing target while the
// breadcrumb still names the level: fall back to the single pane.
setSelected(null)
})
}, [listDirectory])