From dfa68a1d2fdb86b4d6453bb51f4ad0e9dab25afe Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sun, 11 Oct 2026 16:42:43 +0200 Subject: [PATCH] fix(files): keep the items a drag selection covers after letting go --- .../file-browser-shared-folders.test.tsx | 15 +++++++++++++++ components/files/file-browser.tsx | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/components/files/__tests__/file-browser-shared-folders.test.tsx b/components/files/__tests__/file-browser-shared-folders.test.tsx index 1b7fb77dd..87cab69a2 100644 --- a/components/files/__tests__/file-browser-shared-folders.test.tsx +++ b/components/files/__tests__/file-browser-shared-folders.test.tsx @@ -214,6 +214,21 @@ describe('FileBrowser', () => { expect(screen.getAllByRole('button', { name: /upload_files/ }).length).toBeGreaterThan(0); }); + it('keeps a drag selection when the mouse is released', () => { + const onClearSelection = vi.fn(); + const { onSetSelection } = renderBrowser({ props: { onClearSelection, selectedResources: new Set(['notes.txt']) } }); + const area = list().parentElement!; + // jsdom lays everything out at 0,0, so a box from -5,-5 to 20,20 covers every row. + fireEvent.mouseDown(area, { button: 0, clientX: -5, clientY: -5 }); + fireEvent.mouseMove(window, { clientX: 20, clientY: 20 }); + fireEvent.mouseUp(window, { clientX: 20, clientY: 20 }); + fireEvent.click(area); + + expect(onSetSelection).toHaveBeenLastCalledWith(new Set(['Documents', 'notes.txt'])); + // Only the press that started the drag cleared the old selection. + expect(onClearSelection).toHaveBeenCalledTimes(1); + }); + it('replaces the toolbar with selection actions when items are selected', () => { renderBrowser({ props: { selectedResources: new Set(['notes.txt']) } }); const bar = screen.getByRole('toolbar', { name: 'selection_actions' }); diff --git a/components/files/file-browser.tsx b/components/files/file-browser.tsx index 902e58f2c..defb13486 100644 --- a/components/files/file-browser.tsx +++ b/components/files/file-browser.tsx @@ -1043,7 +1043,10 @@ export function FileBrowser({ menu.openContextMenu(e, { kind: "empty" }); }} onClick={(e) => { - if (e.target === e.currentTarget && selectedResources.size > 0 && !marquee) onClearSelection(); + // With a mouse, pressing on empty space already cleared the + // selection, and the click that ends a drag-select lands here + // too: clearing again would drop what was just selected. + if (touch && e.target === e.currentTarget && selectedResources.size > 0) onClearSelection(); }} onDragEnter={handleContentDragEnter} onDragOver={handleContentDragOver}