From 1c9352595cd1b34cdfd8604a6a98574c8428eea2 Mon Sep 17 00:00:00 2001 From: ooiuuii Date: Thu, 8 Oct 2026 19:26:54 -0700 Subject: [PATCH] fix: retire workspace picker results when dismissed --- web/src/workspace/AddWorkspaceDialog.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/web/src/workspace/AddWorkspaceDialog.tsx b/web/src/workspace/AddWorkspaceDialog.tsx index 85261686..55204665 100644 --- a/web/src/workspace/AddWorkspaceDialog.tsx +++ b/web/src/workspace/AddWorkspaceDialog.tsx @@ -68,6 +68,7 @@ export const AddWorkspaceDialog = ({ tRef.current = t }, [t]) const [stage, setStage] = useState({ kind: 'idle' }) + const cancelPendingPickRef = useRef<(() => void) | null>(null) const [commandPresets, setCommandPresets] = useState([]) const [commandPresetId, setCommandPresetId] = useState(DEFAULT_COMMAND_PRESET_ID) const [commandPresetError, setCommandPresetError] = useState(null) @@ -88,6 +89,9 @@ export const AddWorkspaceDialog = ({ useEffect(() => { if (trigger === 0) return let cancelled = false + cancelPendingPickRef.current = () => { + cancelled = true + } setCommandPresetError(null) const presetsReady = listCommandPresets() .then((presets) => { @@ -162,6 +166,7 @@ export const AddWorkspaceDialog = ({ }, [trigger]) const handleCancel = () => { + cancelPendingPickRef.current?.() setStage({ kind: 'idle' }) onClose() } @@ -170,8 +175,7 @@ export const AddWorkspaceDialog = ({ // linger on top of the demo workspace view. const handleTryDemo = onTryDemo ? () => { - setStage({ kind: 'idle' }) - onClose() + handleCancel() onTryDemo() } : undefined @@ -207,11 +211,10 @@ export const AddWorkspaceDialog = ({ if (stage.kind === 'idle') return null if (stage.kind === 'picking') { - // Esc / click-outside cancels the in-flight picker; without onOpenChange - // the dialog was unkillable until the native picker resolved. - const cancelPicking = () => setStage({ kind: 'idle' }) + // Dismiss pending results too: the native picker may have returned while + // presets are still loading, and this component stays mounted after close. return ( - !next && cancelPicking()}> + !next && handleCancel()}>