Repository navigation
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 (ParadevAI#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 ParadevAI#3125 — スキップ (下記参照) - 88bc7fb ParadevAI#3127 — Revert DA1 ✓ - 92d0ff9 ParadevAI#3054 — DA1 fix ✓ - c48450e ParadevAI#3093 — file viewer pane fix ✓ - fffa8db ParadevAI#3128 — version 1.4.7 ✓ - 589a7c7 ParadevAI#3136 — fuzzy scorer (ハイブリッド方式) ✓ - ceb8c81 ParadevAI#3150 — Electron 40.8.5 ✓ - 8922b94 ParadevAI#3137 — terminalId分離 ✓ - c7508e5 ParadevAI#3152 — GitHub無料化 ✓ - 2b91f11 ParadevAI#3155 — v2 terminal theme ✓ - b8b11af ParadevAI#3154 — TUI dimension fix ✓ - 7599ace ParadevAI#3149 — v2 sidebar file tree (手動統合) ✓ - 4d7c612 ParadevAI#3174 — DnD重複削除 ✓ - 864977d ParadevAI#3157 — Host Service分離 ✓ 意図的にスキップ: - be22b46 ParadevAI#3125 (GitHub polling簡素化) フォーク独自のGitHubSyncService (バックエンド集中ポーリング) と 設計が異なるため不採用。upstreamはフロントエンドhover駆動、フォークは バックエンドキャッシュウォーマー方式。詳細は githubQueryPolicy.ts と github-sync-service.ts のFORK NOTEを参照。 ゴースト・マージ復元 (revert 134cfd5 で消失した内容): - 538f306 ParadevAI#3120 — Patch vuln ✓ - 1588d20 ParadevAI#3108 — terminal lifecycle分離 ✓ - 59426f6 ParadevAI#3122 — file tree + FilePane + Alert refactor (手動統合) ✓ - 10d9a5d ParadevAI#3097 — tiptap line-height ✓ - 337a9ae ParadevAI#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