fix(desktop): prevent duplicate panes when file-open mode is new-tab#3093
Conversation
…n mode Decouples the reuse-existing-pane lookup from the openInNewTab flag so that an already-open file is always located first. The pane is still only reused in-place when openInNewTab is false, preventing duplicate panes when the user's file-open mode is set to "new-tab".
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/stores/tabs/store.ts (1)
722-769:⚠️ Potential issue | 🟠 MajorExplicit force-new-tab can be bypassed by workspace-wide file search.
When a file is already open in the workspace, the lookup at lines 759-769 searches across all workspace tabs and returns the existing pane without checking whether
openInNewTabwas explicitly set totrue(e.g., Cmd+click). This prevents creating a new tab as requested.The guard at line 829 (
!options.openInNewTab) only protects the active-tab-only search path and is unreachable if the workspace search succeeds first.Add
&& !isExplicitOpenInNewTabto the lookup gate at line 759 to respect explicit force-new-tab intent:Proposed fix
addFileViewerPane: ( workspaceId: string, options: AddFileViewerPaneOptions, ) => { + const isExplicitOpenInNewTab = options.openInNewTab === true; if (options.openInNewTab === undefined) { options = { ...options, openInNewTab: getFileOpenMode() === "new-tab", }; } const state = get(); const resolvedActiveTabId = resolveActiveTabIdForWorkspace({ workspaceId, tabs: state.tabs, activeTabIds: state.activeTabIds, tabHistoryStacks: state.tabHistoryStacks, }); const activeTab = resolvedActiveTabId ? state.tabs.find((t) => t.id === resolvedActiveTabId) : null; if (!activeTab) { const { tabId, paneId } = get().addTab(workspaceId); const fileViewerPane = createFileViewerPane(tabId, options); set((s) => ({ panes: { ...s.panes, [paneId]: { ...fileViewerPane, id: paneId, }, }, })); return paneId; } const tabPaneIds = extractPaneIdsFromLayout(activeTab.layout); const reuseExisting = options.reuseExisting ?? "workspace"; const existingFileViewerPane = reuseExisting !== "none" && !isExplicitOpenInNewTab ? findReusableFileViewerPane({ workspaceId, activeTabId: activeTab.id, tabs: state.tabs, panes: state.panes, tabHistoryStacks: state.tabHistoryStacks, reuseExisting, options, }) : null;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/stores/tabs/store.ts` around lines 722 - 769, The workspace-wide reuse check can bypass an explicit "open in new tab" request; update the existingFileViewerPane assignment condition so the workspace search is skipped when the user explicitly forced a new tab (i.e., add a guard like && !isExplicitOpenInNewTab or && !options.openInNewTab). Specifically, modify the ternary that sets existingFileViewerPane (the call to findReusableFileViewerPane) to only run when reuseExisting !== "none" AND the explicit-new-tab flag is false, so createFileViewerPane/addTab is used when the user requested a new tab.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/desktop/src/renderer/stores/tabs/store.ts`:
- Around line 722-769: The workspace-wide reuse check can bypass an explicit
"open in new tab" request; update the existingFileViewerPane assignment
condition so the workspace search is skipped when the user explicitly forced a
new tab (i.e., add a guard like && !isExplicitOpenInNewTab or &&
!options.openInNewTab). Specifically, modify the ternary that sets
existingFileViewerPane (the call to findReusableFileViewerPane) to only run when
reuseExisting !== "none" AND the explicit-new-tab flag is false, so
createFileViewerPane/addTab is used when the user requested a new tab.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4f068e53-78d3-4839-a96c-a194d9f20abf
📒 Files selected for processing (1)
apps/desktop/src/renderer/stores/tabs/store.ts
…n mode (superset-sh#3093) Decouples the reuse-existing-pane lookup from the openInNewTab flag so that an already-open file is always located first. The pane is still only reused in-place when openInNewTab is false, preventing duplicate panes when the user's file-open mode is set to "new-tab".
cherry-pick方式で内容を取り込み済みの14コミットをgit履歴上もマージ済みにする。 取り込み済み (cherry-pick / 手動移植): - be22b46 superset-sh#3125 — スキップ (下記参照) - 88bc7fb superset-sh#3127 — Revert DA1 ✓ - 92d0ff9 superset-sh#3054 — DA1 fix ✓ - c48450e superset-sh#3093 — file viewer pane fix ✓ - fffa8db superset-sh#3128 — version 1.4.7 ✓ - 589a7c7 superset-sh#3136 — fuzzy scorer (ハイブリッド方式) ✓ - ceb8c81 superset-sh#3150 — Electron 40.8.5 ✓ - 8922b94 superset-sh#3137 — terminalId分離 ✓ - c7508e5 superset-sh#3152 — GitHub無料化 ✓ - 2b91f11 superset-sh#3155 — v2 terminal theme ✓ - b8b11af superset-sh#3154 — TUI dimension fix ✓ - 7599ace superset-sh#3149 — v2 sidebar file tree (手動統合) ✓ - 4d7c612 superset-sh#3174 — DnD重複削除 ✓ - 864977d superset-sh#3157 — Host Service分離 ✓ 意図的にスキップ: - be22b46 superset-sh#3125 (GitHub polling簡素化) フォーク独自のGitHubSyncService (バックエンド集中ポーリング) と 設計が異なるため不採用。upstreamはフロントエンドhover駆動、フォークは バックエンドキャッシュウォーマー方式。詳細は githubQueryPolicy.ts と github-sync-service.ts のFORK NOTEを参照。 ゴースト・マージ復元 (revert 134cfd5 で消失した内容): - 538f306 superset-sh#3120 — Patch vuln ✓ - 1588d20 superset-sh#3108 — terminal lifecycle分離 ✓ - 59426f6 superset-sh#3122 — file tree + FilePane + Alert refactor (手動統合) ✓ - 10d9a5d superset-sh#3097 — tiptap line-height ✓ - 337a9ae superset-sh#3121 — Codex hooks削除 ✓
Summary
openInNewTabflag inaddFileViewerPaneopenInNewTabis falseScreen.Recording.2026-04-02.at.2.07.41.AM.mov
Test plan
Summary by cubic
Prevent duplicate file-viewer panes when file-open mode is set to "New tab". The store now always finds an existing pane first and only reuses it when
openInNewTabis false, so opening the same file activates the existing tab; split-pane reuse and cmd+click to force a new tab still work as before.Written for commit dd12096. Summary will update on new commits.
Summary by CodeRabbit