Conversation
📝 Walkthroughウォークスルーペイン間のナビゲーションシステムを改新し、前後移動のホットキー( 変更
シーケンスダイアグラムsequenceDiagram
participant User
participant HotkeyHandler as Hotkey Handler
participant Store as Workspace Store
participant LayoutUtils as Layout Utils
participant UI as UI Components
User->>HotkeyHandler: Press FOCUS_PANE_LEFT
HotkeyHandler->>Store: Get active tab & pane
HotkeyHandler->>LayoutUtils: getSpatialNeighborPaneId(layout, currentPaneId, "left")
LayoutUtils->>LayoutUtils: findPanePath(layout, currentPaneId)
LayoutUtils->>LayoutUtils: Traverse to matching-axis ancestor split
LayoutUtils->>LayoutUtils: Select sibling branch & descend
LayoutUtils-->>HotkeyHandler: Neighbor pane ID (or null)
alt Neighbor Found
HotkeyHandler->>Store: setActivePane(tabId, neighborPaneId)
Store->>UI: Update focus state
UI-->>User: Display focused pane
else No Neighbor
HotkeyHandler-->>User: No action (boundary reached)
end
推定コードレビュー努力🎯 4 (複雑) | ⏱️ ~60分 ポエム
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f460cd30c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex レビューへの対応2件の P2 指摘を両方修正しました ( 1. Windows パスセパレータの取り扱い (P2)指摘: 修正: function getFileName(filePath: string): string {
- return filePath.split("/").pop() ?? filePath;
+ return filePath.split(/[/\\]/).pop() || filePath;
}2. v2 useWorkspaceHotkeys の PREV_TAB/NEXT_TAB ハンドラ復元 (P2)指摘: superset-sh#3403 が v2 useWorkspaceHotkeys から 修正: upstream の 検証結果
|
…h#3403) * feat(desktop): directional pane focus via Cmd+Alt+Arrow (v2) Adds spatial pane navigation to v2 workspaces: Cmd+Alt+Arrow jumps focus to the visually adjacent pane in that direction (no wrap at edges). Reclaims Cmd+Alt+Arrow from the retired PREV/NEXT_TAB and PREV/NEXT_WORKSPACE shortcuts — tabs still cycle via Ctrl+Tab and both tabs and workspaces keep Cmd+Alt+1..9 jump-to-N. The spatial neighbor util walks up the LayoutNode path to find the deepest ancestor split whose axis matches the arrow, then descends into the sibling subtree picking the near-edge leaf. * fix(panes): preserve cross-axis alignment during spatial neighbor descent findEdgePaneId previously fell through to node.first on any perpendicular split encountered while descending into the sibling subtree, losing the source pane's row/column position. In a 2x2 grid this caused the directional focus move to land on the wrong pane depending on how the grid was grouped in the layout tree (e.g. in a rows-first 2x2, down from top-right landed on bottom-left). Track the source pane's path below the pivot ancestor as an alignment path and consume one entry per perpendicular-split descent, so the descent mirrors the source's cross-axis choices. Adds unit tests for getSpatialNeighborPaneId covering single pane, simple horizontal/vertical splits, edge no-wrap, and both groupings of the 2x2 grid. * refactor(desktop): drop linear PREV/NEXT_PANE now that directional nav exists The 4-way FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} shortcuts supersede linear pane cycling. Removing PREV/NEXT_PANE also frees ctrl+shift+alt+Arrow on Windows/Linux, which dodges the Intel HD Graphics screen-rotation driver shortcut that steals ctrl+alt+Arrow at the OS level. - Remove PREV_PANE/NEXT_PANE from the hotkey registry and both v1/v2 handler sites. - Remap FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} on Windows/Linux from ctrl+alt+Arrow to ctrl+shift+alt+Arrow. - Delete now-unused getNextPaneId/getPreviousPaneId helpers from renderer/stores/tabs/utils.ts. Users who relied on linear cycling can re-add it via settings once the unbound-default hotkey support lands as a follow-up.
…ne title resolution (superset-sh#3420) * feat(desktop): v2 diff viewer opens in its own tab + pane-derived tab titles openDiffPane now scans all tabs for an existing diff pane (focus + scroll) and falls back to addTab, so clicking a file in the Changes sidebar never hijacks the focused editor tab. Collapses tab/pane title resolution onto a single canonical field: PaneDefinition.getTitle is tightened to (pane) => string, file's rich JSX moves into the existing renderTitle hook, and a new resolveTabTitle helper powers both the tab bar and the "Move to Tab" context menu. tab.titleOverride is reserved for user renames; every auto-default caller is stripped and multi-pane tabs fall back to "Tab N" instead of "tab-<uuid>". * feat(desktop): pane-derived tab titles reserve tab.titleOverride for user renames Preset execution and workspace bootstrap were baking preset.name / terminal.label onto tab.titleOverride, which meant those names persisted misleadingly after a tab was split and couldn't be distinguished from a real user rename. Move both to the pane's titleOverride instead, and teach resolveTabTitle to read pane.titleOverride before falling through to getTitle() for single-pane tabs. tab.titleOverride is now written only by the tab-bar rename action; splitting a named tab flips the label to "Tab N" while the pane keeps its name in its header, and user renames still win over everything. * fix(desktop): browser.getTitle falls back to "Browser" for about:blank Unnavigated browser panes had their pane header fall through to pane.id (a raw UUID) because getTitle returned undefined for about:blank and the old titleOverride: "Browser" default was removed along with the other auto-default titleOverride writes. * fix(desktop): browser tab title uses URL.host to preserve port URL.hostname drops the port, so localhost:3000 and localhost:4000 both rendered as "localhost" in the tab bar. URL.host keeps the port when one is explicitly set.
…ff viewer Follow-up fixes for superset-sh#3403 and superset-sh#3420 cherry-picks: hotkeys/types.ts: - Widen PlatformKey and HotkeyDefinition.key to allow null per platform (mirrors upstream superset-sh#3422; needed here because v1 workspace uses fork's tRPC-based PREV/NEXT_WORKSPACE handlers that reference null-bound keys) hotkeys/registry.ts: - Re-add PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as null-bound (matches upstream superset-sh#3422 final state; deleted by superset-sh#3403's auto-merge but fork still needs the IDs for v1 tRPC-based workspace nav handlers) hotkeys/useRecordHotkeys.ts: - Null-guard canonicalizeChord(defaultKey) so recording a new chord for an unbound hotkey doesn't throw routes/workspace/$workspaceId/page.tsx: - Restore navigateToWorkspace import (removed by cherry-pick auto-merge); fork's tRPC-based PREV/NEXT_WORKSPACE handlers still need it routes/v2-workspace/$workspaceId/page.tsx: - Remove tabTitle argument from openPane call (deprecated by superset-sh#3420; pane-level titleOverride handles tab titles now via resolveTabTitle) FORK NOTE: the registry entries and types.ts widening overlap with PR#2 (superset-sh#3422 cherry-pick). When both PRs merge, git detects identical changes and auto-resolves.
1. Parse file tab titles with Windows path separators (Codex P2)
- getFileName in usePaneRegistry.tsx split on / only, regressing Windows paths
like C:\repo\foo.ts which would render as the full path.
- Use split(/[/\\]/) to handle both separators cross-platform.
2. Restore PREV_TAB/NEXT_TAB handlers in v2 useWorkspaceHotkeys (Codex P2)
- superset-sh#3403 (cherry-picked here) removed these handlers, but superset-sh#3422 (PR#2)
restored them as null-bound in the registry. Without callbacks, users
rebinding these hotkeys in Settings would press them to no effect.
- Add handlers matching upstream c925f4d's restoration so override-based
tab navigation works in v2 workspaces.
a1cfba1 to
d26a7c9
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx (1)
123-137:⚠️ Potential issue | 🟠 Major
displayNameがタブタイトルに反映されていません
renderTitleはdisplayNameを優先していますが、getTitleは常にfilePathの basename を返しています。openFilePane(..., displayName)で開くメモ系タブはヘッダーとタブ名がずれるので、文字列版と ReactNode 版で同じ表示名解決を使った方がよいです。💡 表示名の解決を 1 箇所に寄せる例
function getFileName(filePath: string): string { return filePath.split(/[/\\]/).pop() || filePath; } + +function getFileDisplayName(data: FilePaneData): string { + return data.displayName ?? getFileName(data.filePath); +} @@ - getTitle: (pane) => getFileName((pane.data as FilePaneData).filePath), + getTitle: (pane) => getFileDisplayName(pane.data as FilePaneData), renderTitle: (ctx: RendererContext<PaneViewerData>) => { const data = ctx.pane.data as FilePaneData; - const name = data.displayName ?? getFileName(data.filePath); + const name = getFileDisplayName(data); return (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx around lines 123 - 137, getTitle currently always returns getFileName((pane.data as FilePaneData).filePath) while renderTitle prefers data.displayName, causing tab label/header mismatch for panes opened via openFilePane(..., displayName). Fix by centralizing title resolution: add or use a helper (e.g., resolvePaneTitle or reuse getFileName logic) that returns data.displayName ?? getFileName(data.filePath) for FilePaneData, then have both getTitle and renderTitle call that helper (reference: getTitle, renderTitle, FilePaneData, getFileName, openFilePane, displayName).apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx (1)
288-300:⚠️ Potential issue | 🟠 Major旧レイアウトの diff pane まで再利用してしまいます
ここは
kind === "diff"だけで再利用対象にしているので、以前の実装で保存された「他 pane と同居している diff」を持つワークスペースでも、そのタブに戻ってしまいます。今回の仕様は diff を独立タブで開くことなので、再利用するのは diff 専用タブに限定しないと移行後も旧挙動が残ります。💡 例: 専用 diff タブだけ再利用する
(filePath: string) => { const state = store.getState(); - for (const tab of state.tabs) { - for (const pane of Object.values(tab.panes)) { - if (pane.kind !== "diff") continue; - const prev = pane.data as DiffPaneData; - state.setPaneData({ - paneId: pane.id, - data: { - ...prev, - path: filePath, - } as PaneViewerData, - }); - state.setActiveTab(tab.id); - state.setActivePane({ tabId: tab.id, paneId: pane.id }); - return; - } + for (const tab of state.tabs) { + const panes = Object.values(tab.panes); + if (panes.length !== 1 || panes[0]?.kind !== "diff") continue; + const pane = panes[0]; + const prev = pane.data as DiffPaneData; + state.setPaneData({ + paneId: pane.id, + data: { + ...prev, + path: filePath, + } as PaneViewerData, + }); + state.setActiveTab(tab.id); + state.setActivePane({ tabId: tab.id, paneId: pane.id }); + return; } state.addTab({🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/page.tsx around lines 288 - 300, 現在のループ再利用ロジックは pane.kind === "diff" のみで旧レイアウトの「他 pane と同居する diff」まで再利用してしまうので、diff 専用タブに限定するチェックを追加してください:ループ内で tab(state.tabs の要素)を調べ、当該 tab が専用 diff タブであること(例:Object.values(tab.panes).every(p => p.kind === "diff") またはタブに専用フラグがあればそれを使う)を確認してから DiffPaneData を prev として state.setPaneData / state.setActiveTab / state.setActivePane を呼ぶように変更してください。
🧹 Nitpick comments (1)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useV2PresetExecution/useV2PresetExecution.ts (1)
90-188:preset.name || undefinedは変数化して重複を減らしたいです。同じ式が複数分岐で繰り返されているため、1 か所に寄せると可読性と変更耐性が上がります。
リファクタ案
try { + const paneTitleOverride = preset.name || undefined; switch (plan) { case "new-tab-single": { const id = await createSessionWithCommand( preset.commands[0] as string, ); state.addTab({ - panes: [makeTerminalPane(id, preset.name || undefined)], + panes: [makeTerminalPane(id, paneTitleOverride)], }); break; } @@ - const panes = ids.map((id) => - makeTerminalPane(id, preset.name || undefined), - ); + const panes = ids.map((id) => makeTerminalPane(id, paneTitleOverride));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/useV2PresetExecution/useV2PresetExecution.ts around lines 90 - 188, The repeated expression preset.name || undefined is duplicated across multiple cases in the switch inside useV2PresetExecution; extract it into a single const (e.g., paneTitle or titleFallback) declared before the switch (or at top of the switch block) and replace every occurrence passed to makeTerminalPane(...) with that variable (affecting cases "new-tab-single", "new-tab-multi-pane", "new-tab-per-command", "active-tab-single", and "active-tab-multi-pane"); ensure the variable is used for all makeTerminalPane calls so the value is calculated once and duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx:
- Around line 47-49: The onBeforeClose handler still uses a hardcoded split("/")
to derive basenames while getFileName(filePath: string) already handles both "/"
and "\\"; update onBeforeClose to call getFileName(...) wherever it currently
does filePath.split("/") (or similar) so the dirty-file confirmation dialog
shows the basename consistently on Windows and POSIX systems, and scan the same
file for any other remaining split("/") usages and replace them with
getFileName.
In `@packages/panes/src/react/components/Workspace/utils/resolveTabTitle.ts`:
- Line 17: The fallback title uses tabs.indexOf(tab) which can return -1 for
different object references, producing "Tab 0"; change the logic in
resolveTabTitle to compute the index by id (use tabs.findIndex(t => t.id ===
tab.id) or equivalent) and ensure you guard against -1 by falling back to 0
before adding 1 (e.g., index = Math.max(foundIndex, 0)); update the return that
currently uses tabs.indexOf(tab) to use this id-based index calculation so
titles are stable across reference mismatches.
---
Outside diff comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx:
- Around line 123-137: getTitle currently always returns getFileName((pane.data
as FilePaneData).filePath) while renderTitle prefers data.displayName, causing
tab label/header mismatch for panes opened via openFilePane(..., displayName).
Fix by centralizing title resolution: add or use a helper (e.g.,
resolvePaneTitle or reuse getFileName logic) that returns data.displayName ??
getFileName(data.filePath) for FilePaneData, then have both getTitle and
renderTitle call that helper (reference: getTitle, renderTitle, FilePaneData,
getFileName, openFilePane, displayName).
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/page.tsx:
- Around line 288-300: 現在のループ再利用ロジックは pane.kind === "diff" のみで旧レイアウトの「他 pane
と同居する diff」まで再利用してしまうので、diff 専用タブに限定するチェックを追加してください:ループ内で tab(state.tabs
の要素)を調べ、当該 tab が専用 diff タブであること(例:Object.values(tab.panes).every(p => p.kind ===
"diff") またはタブに専用フラグがあればそれを使う)を確認してから DiffPaneData を prev として state.setPaneData /
state.setActiveTab / state.setActivePane を呼ぶように変更してください。
---
Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/useV2PresetExecution/useV2PresetExecution.ts:
- Around line 90-188: The repeated expression preset.name || undefined is
duplicated across multiple cases in the switch inside useV2PresetExecution;
extract it into a single const (e.g., paneTitle or titleFallback) declared
before the switch (or at top of the switch block) and replace every occurrence
passed to makeTerminalPane(...) with that variable (affecting cases
"new-tab-single", "new-tab-multi-pane", "new-tab-per-command",
"active-tab-single", and "active-tab-multi-pane"); ensure the variable is used
for all makeTerminalPane calls so the value is calculated once and duplication
is removed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4273840b-872d-4b71-bfac-f9f0d5e0aa3e
📒 Files selected for processing (23)
apps/desktop/src/renderer/hotkeys/registry.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/buildSetupPaneLayout.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useDefaultContextMenuActions/useDefaultContextMenuActions.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/BrowserPane/BrowserPane.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/BrowserPane/index.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useV2PresetExecution/useV2PresetExecution.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsxapps/desktop/src/renderer/stores/tabs/utils.tspackages/panes/src/core/store/store.test.tspackages/panes/src/core/store/store.tspackages/panes/src/core/store/utils/index.tspackages/panes/src/core/store/utils/utils.test.tspackages/panes/src/core/store/utils/utils.tspackages/panes/src/index.tspackages/panes/src/react/components/Workspace/Workspace.tsxpackages/panes/src/react/components/Workspace/components/Tab/components/Pane/Pane.tsxpackages/panes/src/react/components/Workspace/index.tspackages/panes/src/react/components/Workspace/utils/resolveTabTitle.tspackages/panes/src/react/index.tspackages/panes/src/react/types.ts
💤 Files with no reviewable changes (4)
- packages/panes/src/core/store/store.test.ts
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/BrowserPane/index.ts
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/BrowserPane/BrowserPane.tsx
- apps/desktop/src/renderer/stores/tabs/utils.ts
| function getFileName(filePath: string): string { | ||
| return filePath.split("/").pop() ?? filePath; | ||
| return filePath.split(/[/\\]/).pop() || filePath; | ||
| } |
There was a problem hiding this comment.
basename の解決をこの helper に寄せ切れていません
この helper 自体は直っていますが、同じファイルの onBeforeClose はまだ split("/") のままです。Windows では dirty-file の確認ダイアログだけフルパス表示が残るので、basename 解決は getFileName() に一本化した方が安全です。
💡 併せて置き換えておくと安全です
- const name = data.filePath.split("/").pop();
+ const name = getFileName(data.filePath);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx
around lines 47 - 49, The onBeforeClose handler still uses a hardcoded
split("/") to derive basenames while getFileName(filePath: string) already
handles both "/" and "\\"; update onBeforeClose to call getFileName(...)
wherever it currently does filePath.split("/") (or similar) so the dirty-file
confirmation dialog shows the basename consistently on Windows and POSIX
systems, and scan the same file for any other remaining split("/") usages and
replace them with getFileName.
| onlyPane.titleOverride ?? registry[onlyPane.kind]?.getTitle?.(onlyPane); | ||
| if (fromPane) return fromPane; | ||
| } | ||
| return `Tab ${tabs.indexOf(tab) + 1}`; |
There was a problem hiding this comment.
フォールバックタイトルが Tab 0 になり得ます。
tabs.indexOf(tab) は参照一致前提なので、同一 id でも別参照の tab が渡ると -1 になり、Tab 0 が表示されます。id ベースで index を解決する方が安全です。
修正案
- return `Tab ${tabs.indexOf(tab) + 1}`;
+ const index = tabs.findIndex((t) => t.id === tab.id);
+ return `Tab ${index >= 0 ? index + 1 : 1}`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return `Tab ${tabs.indexOf(tab) + 1}`; | |
| const index = tabs.findIndex((t) => t.id === tab.id); | |
| return `Tab ${index >= 0 ? index + 1 : 1}`; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/panes/src/react/components/Workspace/utils/resolveTabTitle.ts` at
line 17, The fallback title uses tabs.indexOf(tab) which can return -1 for
different object references, producing "Tab 0"; change the logic in
resolveTabTitle to compute the index by id (use tabs.findIndex(t => t.id ===
tab.id) or equivalent) and ensure you guard against -1 by falling back to 0
before adding 1 (e.g., index = Math.max(foundIndex, 0)); update the return that
currently uses tabs.indexOf(tab) to use this id-based index calculation so
titles are stable across reference mismatches.
All 9 upstream commits have been individually cherry-picked via PR#159~#163: | Upstream | Our PR | Description | |---|---|---| | d656b7e (superset-sh#3415) | #159 (PR#1) | terminal clipboard handling | | 31fcf19 (superset-sh#3416) | #162 (PR#4) | v1 split pane startup sizing fix | | 039edf2 (superset-sh#3403) | #161 (PR#3) | Cmd+Alt+Arrow spatial pane focus | | b18a00c (superset-sh#3421) | #159 (PR#1) | v2 right sidebar toggle reactive | | 3dd1de2 (superset-sh#3420) | #161 (PR#3) | v2 diff viewer + tab title resolution | | b42a114 (superset-sh#3418) | #159 (PR#1) | CodeMirror hotkey enablement | | c925f4d (superset-sh#3422) | #160 (PR#2) | unbound defaults + restore prev/next tab/workspace | | bb12c09 (superset-sh#3419) | #163 (PR#5) | version bump 1.5.3 | | 47efa73 (superset-sh#3432) | #159 (PR#1) | pending/update-required error selectable | Fork-specific features preserved: - auto-updater (IS_FORK, GitHub Releases API) - QuitMode/cleanupMainWindowResources lifecycle - GitHubSyncService, SpreadsheetViewer - BROWSER_RELOAD / BROWSER_HARD_RELOAD / SEARCH_IN_FILES hotkeys - HotkeyCategory "Browser" - v1 deep-link navigation (useSearch/WorkspaceSearchParams) - v1 tRPC-based PREV/NEXT_WORKSPACE handlers - v1 CLOSE_TERMINAL/CLOSE_TAB hotkey handlers - v2 extra state (rightSidebarOpenViewWidth, showPresetsBar)
Upstream Merge PR#3 - 空間認識ペインナビ + Diff ビューア
upstream から2つの大きな機能改善コミットを cherry-pick します。フォークにとって初の 大規模 API 変更 を含みます。
取り込むコミット
改善内容の詳細
① 空間認識型ペインナビゲーション (superset-sh#3403)
何が問題だったか
従来の `PREV_PANE` / `NEXT_PANE` は 線形循環 でした:
どう直したか
4方向の空間認識型ナビゲーションに刷新:
```
FOCUS_PANE_LEFT → Cmd+Alt+Left (mac) / Ctrl+Shift+Alt+Left (win/linux)
FOCUS_PANE_RIGHT → Cmd+Alt+Right (mac) / Ctrl+Shift+Alt+Right (win/linux)
FOCUS_PANE_UP → Cmd+Alt+Up (mac) / Ctrl+Shift+Alt+Up (win/linux)
FOCUS_PANE_DOWN → Cmd+Alt+Down (mac) / Ctrl+Shift+Alt+Down (win/linux)
```
新規アルゴリズム `getSpatialNeighborPaneId()`:
この整合性ロジックはバグ修正が重なってテストが追加されています:
Windows/Linux での Intel ドライバ回避:
新規ファイル:
② Diff ビューア独立タブ + タブタイトル解決API刷新 (superset-sh#3420)
何が問題だったか
Diff ビューアが既存タブに埋め込まれる:
タブタイトルの責任が散らかっていた:
どう直したか
(a) Diff ビューアが独立タブで開く
(b) `PaneDefinition.getTitle()` API の刷新
```typescript
// Before
interface PaneDefinition {
getTitle?(context: RendererContext): ReactNode;
}
// After
interface PaneDefinition {
getTitle?(pane: Pane): string | undefined; // 純粋な文字列のみ
renderTitle?(context: RendererContext): ReactNode; // JSX はこちらへ
}
```
これにより:
(c) `titleOverride` をタブ→ペインレベルへ移動
```
Before:
tab.titleOverride ← ユーザー rename と preset 名と terminal label が混在
After:
tab.titleOverride ← ユーザー rename 専用(タブ分割時にクリア)
pane.titleOverride ← preset 名 / terminal label (pane 固有のラベル)
```
(d) 新規ヘルパー `resolveTabTitle()`
タブタイトル解決を一元化:
```typescript
// packages/panes/src/react/components/Workspace/utils/resolveTabTitle.ts
function resolveTabTitle(tab, tabs, registry) {
// 1. tab.titleOverride(ユーザー rename)が最優先
if (tab.titleOverride) return tab.titleOverride;
// 2. 単一ペインの場合:
// - pane.titleOverride
// - registry[pane.kind].getTitle(pane)
const onlyPane = single pane ? ... : undefined;
if (onlyPane) {
const fromPane = onlyPane.titleOverride ?? registry[...]?.getTitle?.(onlyPane);
if (fromPane) return fromPane;
}
// 3. 複数ペインの場合: "Tab N"
return `Tab ${tabs.indexOf(tab) + 1}`;
}
```
(e) ブラウザタブのタイトルが URL のポート番号を保持
(f) `WorkspaceProps.getTabTitle` を削除、`openPane({ tabTitle })` を廃止
コンフリクト解決
v1 workspace/$workspaceId/page.tsx
v2 workspace/$workspaceId/page.tsx
registry.ts
追加の型拡張(PR#2 と重複)
cherry-pick 後の typecheck パスのため、以下を追加:
フォーク固有機能の保持
テスト計画
Summary by CodeRabbit
Release Notes
New Features
Refactor
Tests