Skip to content

fix(desktop): prevent duplicate panes when file-open mode is new-tab#3093

Merged
Kitenite merged 1 commit into
superset-sh:mainfrom
Ipriyankrajai:fix/tab-open
Apr 3, 2026
Merged

fix(desktop): prevent duplicate panes when file-open mode is new-tab#3093
Kitenite merged 1 commit into
superset-sh:mainfrom
Ipriyankrajai:fix/tab-open

Conversation

@Ipriyankrajai
Copy link
Copy Markdown
Contributor

@Ipriyankrajai Ipriyankrajai commented Apr 1, 2026

Summary

  • Decouples the existing-pane lookup from the openInNewTab flag in addFileViewerPane
  • Previously, when file-open mode was set to "new-tab", the store skipped searching for an already-open pane entirely, which could create duplicates
  • Now the store always finds an existing pane first, but only reuses it in-place when openInNewTab is false
Screen.Recording.2026-04-02.at.2.07.41.AM.mov

Test plan

  • Set file-open mode to "New tab" in Settings → Behavior
  • Open a file — verify it opens in a new tab
  • Open the same file again — verify it activates the existing tab instead of creating a duplicate
  • Set file-open mode to "Split pane" and verify normal split-pane reuse still works
  • Cmd+click a file (force new tab) — verify it still opens in a new tab

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 openInNewTab is 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

  • Refactor
    • Streamlined internal logic for managing file viewer pane reuse behavior.

…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".
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 1, 2026

📝 Walkthrough

Walkthrough

The addFileViewerPane function in the tabs store was refactored to simplify reuse logic for file-viewer panes. An intermediate canReuseExistingPane boolean variable was removed, with its reuse condition now directly inlined in both relevant code paths where the pane reuse decision is made.

Changes

Cohort / File(s) Summary
Tabs Store Refactoring
apps/desktop/src/renderer/stores/tabs/store.ts
Removed intermediate canReuseExistingPane boolean; inlined reuse condition (!options.openInNewTab && reuseExisting !== "none") directly in both code paths for consistency and clarity.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

A variable hopped away with a bound,
Its logic now flows without making a sound—
Two paths sing the same simple refrain,
Simplicity blooms like clover again! 🐰✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main fix: preventing duplicate panes when file-open mode is set to new-tab, which matches the core change in the PR.
Description check ✅ Passed The description includes a clear summary, detailed explanation of the problem and solution, comprehensive test plan with verification steps, and supporting video evidence. However, required template sections like 'Type of Change', 'Related Issues', and 'Testing' checkboxes are not fully completed in the standard format.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Explicit 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 openInNewTab was explicitly set to true (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 && !isExplicitOpenInNewTab to 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

📥 Commits

Reviewing files that changed from the base of the PR and between a2e9531 and dd12096.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/stores/tabs/store.ts

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

@Kitenite Kitenite merged commit c48450e into superset-sh:main Apr 3, 2026
6 of 7 checks passed
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 5, 2026
…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".
MocA-Love added a commit to MocA-Love/superset that referenced this pull request Apr 5, 2026
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削除 ✓
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants