From b0d120efa8dbf728c04643df47830886de011fa1 Mon Sep 17 00:00:00 2001 From: creatixchu Date: Wed, 29 Jul 2026 00:38:37 +0800 Subject: [PATCH] fix(host): cancelling a superseded path edit falls back to the single-pane level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A draft edit can invalidate the selection's preview request; Escape then left selected set with no child and nothing loading — a half-empty two-pane view. Cancel now clears the selection when no preview exists (ds-review-bot round 7). --- .../src/client/DirectoryBrowser.tsx | 5 +++++ .../tests/directory-browser.spec.tsx | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx index b91ac5311d..e224d690d5 100644 --- a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx +++ b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx @@ -328,6 +328,11 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen, event.stopPropagation() setPathDraft(null) setError(null) + // Editing may have superseded the selection's preview + // request; a selection with no preview and nothing in + // flight would render a half-empty two-pane view, so + // cancel falls back to the single-pane level. + if (child === null && !loading) setSelected(null) } }} /> diff --git a/packages/host/directory-picker-browse/tests/directory-browser.spec.tsx b/packages/host/directory-picker-browse/tests/directory-browser.spec.tsx index 2fae7adbda..21cba12d9f 100644 --- a/packages/host/directory-picker-browse/tests/directory-browser.spec.tsx +++ b/packages/host/directory-picker-browse/tests/directory-browser.spec.tsx @@ -355,6 +355,23 @@ describe('DirectoryBrowser', () => { expect(screen.queryByText('harness')).toBeNull() }) + it('falls back to the single-pane level when a path edit superseded the preview and was cancelled', async () => { + const pending: ((listing: DirectoryListing) => void)[] = [] + const b = mount() + await waitFor(() => { expect(screen.getByRole('listitem')).toBeTruthy() }) + // Selection starts a preview that never lands (superseded below). + b.listDirectory.mockImplementation(() => + new Promise((settle) => { pending.push(settle) })) + fireEvent.click(rowButton(screen.getByRole('listitem'))) + fireEvent.click(screen.getByRole('button', { name: 'browser.editPath' })) + const input = screen.getByLabelText('browser.editPath') + fireEvent.change(input, { target: { value: `${DOCS}/x` } }) + fireEvent.keyDown(input, { key: 'Escape' }) + // No half-empty two-pane residue: back to the single wide level. + expect(columns()).toHaveLength(1) + expect(screen.getByRole('button', { name: 'browser.editPath' })).toBeTruthy() + }) + it('ignores dismissal while adoption is busy', async () => { const b = mount({ busy: true }) await waitFor(() => { expect(screen.getByRole('dialog')).toBeTruthy() })