fix(host,client): stream bounded listings, declare schemastery, guard Choose again

The browse level now streams through opendir into a name-sorted window of
maxEntries + 1 candidates (boundedInsert), so memory stays O(maxEntries)
no matter how many children a directory holds and enterability probing
touches only windowed candidates; a windowed broken symlink is not
backfilled since the eviction already marks the level truncated.
schemastery joins the package's runtime dependencies (the source launcher
and isolated installs failed to resolve the value import). The
folder-error dialog's Choose again goes inert while the flow hole is
empty, and the withdrawal effect also keys on the open transition, so a
flow can never open over a hole nobody serves.
This commit is contained in:
creatixchu
2026-07-29 04:11:41 +08:00
parent 5245182db2
commit da970ea269
13 changed files with 116 additions and 29 deletions

View File

@@ -98,9 +98,12 @@ export function WorkspaceCreateFlow({
const flowAvailable = useDirectoryFlow(occupied => occupied)
// An occupant that unloads mid-interaction leaves nobody to cancel: an
// open flow over an empty hole withdraws so the menu actions come back.
// flowOpen is a dependency because the flow can also OPEN over an already
// empty hole (Choose again after the occupant unloaded with the error
// dialog up) — that transition must snap back too, not just occupancy loss.
useEffect(() => {
if (!flowAvailable) setFlowOpen(false)
}, [flowAvailable])
if (flowOpen && !flowAvailable) setFlowOpen(false)
}, [flowOpen, flowAvailable])
const createEntries: MenuEntry[] = [
...(flowAvailable
? [{ id: OPEN_LOCAL_FOLDER, label: 'Open local folder…', icon: <IconFolderClose16 size={16} />, disabled: flowBusy }]
@@ -224,7 +227,9 @@ export function WorkspaceCreateFlow({
footer={(
<>
<Button variant="outline" className={css.modalAction} onClick={closeModal}>Cancel</Button>
<Button variant="primary" className={css.modalAction} onClick={openLocalFolder}>Choose again</Button>
{/* Retrying needs an occupant to serve the flow; without one the
* button would open a flow nobody can answer or cancel. */}
<Button variant="primary" className={css.modalAction} disabled={!flowAvailable} onClick={openLocalFolder}>Choose again</Button>
</>
)}
>

View File

@@ -303,6 +303,20 @@ describe('WorkspacePicker', () => {
expect(screen.getByRole('menuitem', { name: 'Open local folder…' })).toBeTruthy()
})
it('keeps Choose again inert while the flow occupant is gone, and snaps back a flow opened over an empty hole', async () => {
const b = mount([], vi.fn(async () => { throw new Error('adoption failed') }))
chooseItem('Open local folder…')
await act(async () => { b.probe.owner!.onPicked('/one/project') })
await waitFor(() => { expect(screen.getByRole('dialog', { name: 'Couldnt open folder' })).toBeTruthy() })
// The occupant unloads while the error dialog is up: retrying would open
// a flow nobody can serve or cancel, so the button goes inert.
act(() => { b.occupancy.flip(false) })
expect(screen.getByRole<HTMLButtonElement>('button', { name: 'Choose again' }).disabled).toBe(true)
// Cancel stays the way out, and the menu actions are usable again.
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }))
expect(screen.getByRole<HTMLButtonElement>('menuitem', { name: 'Create a new workspace' }).disabled).toBe(false)
})
it('withdraws an open flow when its occupant unloads, re-enabling the menu actions', () => {
const b = mount([])
chooseItem('Open local folder…')