From cd25a9f4053c603756209b22ba9b91da4257a893 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Mon, 27 Jul 2026 17:55:24 -0500 Subject: [PATCH] fix(desktop): open a preview without dragging the file tree open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The preview pane shares a collapsible column with the file tree, and `revealTreePane` un-collapses a column through that column's bound store — which on the right is `$fileBrowserOpen`, the tree's own ⌘J toggle. So every preview open literally called `setFileBrowserOpen(true)` and the tree came with it. `revealPreview` now un-collapses the column directly and leaves the toggle alone. The tree pane's visibility binding gains `$fileBrowserOpen` to match, since its presence was tracking only the column's collapse — without that it would still render the moment anything opened the column. --- apps/desktop/src/app/contrib/controller.tsx | 22 ++++++++++++- .../pane-shell/tree/reactive-unhide.test.ts | 32 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/apps/desktop/src/app/contrib/controller.tsx b/apps/desktop/src/app/contrib/controller.tsx index 92eb08b63d3..6994be8431c 100644 --- a/apps/desktop/src/app/contrib/controller.tsx +++ b/apps/desktop/src/app/contrib/controller.tsx @@ -27,6 +27,8 @@ import { revealTreePane, setPaneCollapsed, setTreePaneHidden, + setTreeSideCollapsed, + treeSideOfPane, watchContributedPanes } from '@/components/pane-shell/tree/store' import { SidebarProvider } from '@/components/ui/sidebar' @@ -533,7 +535,13 @@ bindTreeSideVisibility('right', $fileBrowserOpen, setFileBrowserOpen) // rode the rail's row and vanished with it), its zone stands on its own. const $hasWorkspace = computed($currentCwd, cwd => Boolean(cwd.trim())) -bindPaneVisibility('files', $hasWorkspace) +// The tree pane's own presence tracks ⌘J directly, not just the column's +// collapse — otherwise revealing a preview (which opens that shared column) +// would drag the tree along with it. See revealPreview. +bindPaneVisibility( + 'files', + computed([$hasWorkspace, $fileBrowserOpen], (workspace, open) => workspace && open) +) // ⌘G — the review sidebar appears/disappears (and comes to the front). bindPaneVisibility( 'review', @@ -596,6 +604,18 @@ registerPaneCloser('files', () => // the side, unhide, front — a NEW target while already visible still fronts. const revealPreview = () => { dockPaneBeside('preview', 'files') + + // The preview shares a collapsible column with the file tree, and + // revealTreePane un-collapses a column through its bound store — here ⌘J / + // $fileBrowserOpen, which IS the tree's toggle. Going through it would open + // the tree every time a preview opened. Un-collapse the column directly and + // leave the toggle alone, so a preview can appear on its own. + const side = treeSideOfPane('preview') + + if (side) { + setTreeSideCollapsed(side, false) + } + revealTreePane('preview') } diff --git a/apps/desktop/src/components/pane-shell/tree/reactive-unhide.test.ts b/apps/desktop/src/components/pane-shell/tree/reactive-unhide.test.ts index 90244a96c27..bb6153f50eb 100644 --- a/apps/desktop/src/components/pane-shell/tree/reactive-unhide.test.ts +++ b/apps/desktop/src/components/pane-shell/tree/reactive-unhide.test.ts @@ -127,6 +127,38 @@ describe('reactive pane unhide', () => { expect(tree.$collapsedTreeSides.get().has('right')).toBe(false) }) + // Opening a preview used to drag the file tree open with it: the preview + // shares ⌘J's column, and `revealTreePane` un-collapses a column through its + // bound store — which for the right side IS the file-browser toggle. The + // reveal now un-collapses the column directly and leaves the toggle alone. + it('revealing a preview opens its column without flipping the file-tree toggle', async () => { + const { tree, layout } = await setupWithFiles() + const { registry } = await import('@/contrib/registry') + + registry.register({ + id: 'preview', + area: 'panes', + data: { placement: 'right' }, + render: () => null, + title: 'preview' + }) + + layout.setFileBrowserOpen(false) + expect(tree.$collapsedTreeSides.get().has('right')).toBe(true) + + // The revealPreview sequence from controller.tsx. + const side = tree.treeSideOfPane('files') + + expect(side).toBe('right') + tree.setTreeSideCollapsed(side!, false) + tree.revealTreePane('preview') + + // The column is showing… + expect(tree.$collapsedTreeSides.get().has('right')).toBe(false) + // …but the tree's own toggle never moved, so the tree stays closed. + expect(layout.$fileBrowserOpen.get()).toBe(false) + }) + it('reactive unhide does not invoke the right side opener directly', async () => { const { tree, layout } = await setupWithFiles()