merge: upstream/main 14コミットを取り込み#3004
Conversation
Add the ability to view .xlsx, .xls, .xlsm, .xlsb, and .ods files natively instead of showing "Binary file preview not supported". Features: - Full spreadsheet rendering with ExcelJS (formatting, borders, merged cells, fonts, colors, theme colors with tint, rich text, row heights, text wrapping, vertical text) - Print area aware column/row range detection - Auto fit-to-width column scaling - Multiple sheet tab navigation - Side-by-side diff viewer with cell-level change highlighting - Diff navigation (Prev/Next) with synchronized scrolling - Git binary file read via new readGitFileBinary tRPC procedure
feat(desktop): add Excel/spreadsheet viewer with diff support
Electron's <webview> tag reloads its content whenever the element is reparented in the DOM. The previous approach rendered only the active tab, causing BrowserPane to unmount on every tab switch and park the webview in a hidden container (DOM reparent) — triggering a hard reload. - Add PersistentTabRenderer that keeps all workspace tabs mounted and hides inactive ones via off-screen positioning (not display:none, which stops Electron's compositor) - Wrap each webview in a persistent wrapper div so the webview's parentNode never changes during park/reclaim cycles - Use unique Mosaic IDs per tab to prevent drag-drop conflicts between simultaneously mounted Mosaic instances
Keep workspace pages mounted across workspace switches so that webview elements are never removed from the DOM. - Add KeepAliveWorkspaces component that replaces <Outlet /> for workspace routes, rendering all visited workspaces simultaneously and hiding inactive ones off-screen - Make WorkspacePage accept workspaceId as a prop override so it works outside the router's matched-route context - Thread workspaceId through WorkspaceLayout → ContentView → TabsContent via props instead of useParams(), preventing hidden workspaces from reading the wrong workspace ID from the active route
…p-alive When multiple WorkspacePage instances are mounted simultaneously (KeepAliveWorkspaces), several issues occurred: 1. Components using useParams() read the ACTIVE workspace's ID instead of their own — causing wrong files, wrong sidebar data, and wrong tab lists. Fixed by introducing WorkspaceIdContext and replacing useParams() with useWorkspaceId() in 9 affected components. 2. Mosaic drag-drop was broken because GroupItem used a static mosaicId that no longer matched the per-tab dynamic ID. Fixed by computing the active tab's mosaicId dynamically. 3. All workspace hotkeys fired for every mounted workspace. Fixed by passing `enabled: isActive` to all useAppHotkey calls so only the active workspace responds to keyboard shortcuts.
Electron's <webview> tags consume mouse events in their guest process, so mouse back/forward buttons (button 3/4) never reach the host renderer's event listeners. Handle the `app-command` event on the main BrowserWindow to intercept `browser-backward` and `browser-forward` commands, forwarding them to the focused webview's navigation history. Also update usePresetHotkeys to accept an options parameter for consistency with the enabled-flag pattern used across workspace hotkeys.
The `app-command` event is Windows/Linux only — it never fires on macOS. Instead, inject a mouse event listener into the webview guest page via executeJavaScript on every `dom-ready`. The injected script calls `history.back()` / `history.forward()` directly inside the guest when mouse buttons 3/4 are pressed. The existing `app-command` handler in the main process is kept as a fallback for Windows/Linux.
…spaces PersistentTabRenderer now only keeps tabs mounted when they contain a webview pane. Tabs with only terminals, chat, or file viewers unmount normally on tab switch, reducing memory usage. KeepAliveWorkspaces now watches the workspace list from the database and automatically removes deleted workspaces from the keep-alive set, preventing stale WorkspacePage instances from lingering in memory.
Keep both our useWorkspaceId import and main's new githubQueryPolicy imports. The useParams import was already removed by our branch.
Auto-update pointed to the upstream repo (superset-sh/superset), which would overwrite fork-specific changes on install. - Disable autoDownload and autoInstallOnAppQuit - Replace "Install" button with "Open releases" that opens the fork's GitHub releases page (MocA-Love/superset) - Update toast copy to say "available upstream" instead of "ready to install"
fix(desktop): 自動更新を無効化しフォークのリリースページへ誘導
- Remove redundant `genericNavigate` declaration; reuse existing `navigate` from useNavigate() - Gate mouse-nav shim injection to macOS only (PLATFORM.IS_MAC); Windows/Linux already handle side buttons via `app-command`
fix(desktop): prevent browser webview reload on tab/workspace switch
Add a sparkle button to the commit message input that generates a conventional commit message using the configured AI provider (OpenAI or Anthropic). Uses the existing callSmallModel infrastructure with automatic provider fallback. - Gathers staged, unstaged, and untracked file changes for context - Supports both OAuth and API key authentication for OpenAI - Generates messages in Japanese with conventional commit format - Logs detailed provider diagnostics on failure
…generation
Replace the simple truncated-diff approach with a gptcommit-style
two-phase strategy for the highest accuracy on large diffs:
Phase 1: Summarize each changed file independently in parallel via LLM.
- Lock files, binaries, and other low-value files are skipped
(file names only passed to Phase 2)
- Small diffs (<300 chars) are passed directly without an LLM call
- Large per-file diffs are truncated at 4000 chars before summarizing
Phase 2: Combine all file summaries + diff stats into a single prompt
and generate the final conventional commit message.
This avoids token-limit truncation that loses important context and
produces significantly better messages for multi-file changes.
feat(desktop): AIコミットメッセージ自動生成
The existing @pierre/diffs diff viewer renders all lines at once, causing severe lag on files with 2000+ lines (~180k+ DOM nodes). Add CodeMirrorDiffViewer using @codemirror/merge which provides virtualized rendering (only visible lines in DOM). Files with >2000 total lines automatically use this viewer instead. - Reuses existing CodeMirror theme, fonts, and syntax highlighting - Unchanged regions are collapsed (margin: 3, minSize: 4) - Read-only side-by-side view with line numbers - No changes to LightDiffViewer (small files use it as before)
The default scanLimit (500) causes the diff algorithm to fall back to an imprecise mode for large files, marking everything as changed. Increase to 50000 with a 5s timeout.
Keep context menu actions (split, move, close, edit at location) available for large file diffs. Also conditionally skip MarkdownSearch and DiffScrollbarDecorations for CodeMirror path since they are @pierre/diffs specific.
feat(desktop): 大規模ファイル向け CodeMirror diff ビューア
- Add drag-to-resize handle on the ports section border, allowing users to adjust the height (80–600px, persisted to localStorage) - Add filter toggle button (funnel icon) to show only ports defined in ports.json, hiding auto-detected ports - Fix layout so ports list can expand by using shrink-0 and explicit height instead of max-height
feat(desktop): Excelセルのインラインdiff表示
- ExtensionPopupManager: フレームレスBrowserWindowでpopup.htmlを表示 - chrome-extension:// URLでロード、同一session partitionで通信自動対応 - enablePreferredSizeModeによる自動サイズ調整 - blurイベントで自動クローズ、同時1つのみ排他制御 - アイコン直下に配置、画面端クランプ対応 - extension-icon-protocol: superset-ext-icon:// プロトコルでアイコン画像配信 - ExtensionToolbar/ExtensionIcon: BrowserPaneツールバーに拡張アイコン表示 - tRPC: listToolbarExtensions/openPopup/closePopup エンドポイント追加 - 互換性チェッカーからpopup "unsupported" 警告を削除
- sandbox: true が chrome-extension:// プロトコルをブロックしていた問題を修正 - chrome-extension:// ロード失敗時に file:// からの直接ロードにフォールバック - 未使用変数を削除
ダークモード時に白文字が白背景で見えなくなる問題を修正。 nativeTheme.shouldUseDarkColors に合わせて背景色を設定。
CRX展開時にmanifestのkeyフィールドが失われるため、Electronが Chrome Web Store IDとは異なるIDを割り当てる。loadExtension()の 戻り値からelectronIdを取得・永続化し、popup URLに使用するよう修正。
feat(desktop): Chrome Web Store拡張機能インストール + ツールバーUI
# Conflicts: # apps/desktop/src/lib/trpc/routers/changes/git-operations.ts # bun.lock
ツールバーにトグルボタンを追加し、ONにするとファイル/フォルダ名に 相対パスのツールチップを表示。設定はZustandで永続化。 Closes #21
feat(desktop): Filesタブにファイル名ツールチップ
webviewのコンテキストメニューにDevTools検証機能を追加し、 右クリック位置の要素を直接インスペクトできるようにした。
feat(desktop): ブラウザペインに Inspect Element を追加
~/.zsh_history から入力中のプレフィックスに一致するコマンドを候補表示。 ゴーストテキスト+ドロップダウンリストで候補を表示し、↑↓で選択、→で確定、 Escで破棄。設定画面からON/OFF切り替え可能(デフォルトON)。 末尾到達時に追加候補を自動読み込み。
getGitHubStatus / getGitHubPRComments が worktree レコード必須だった 制限を解消し、type=branch のワークスペースでは mainRepoPath に フォールバックして gh CLI を実行するように変更
候補が8件を超える場合、リストが固定高さ内でスクロールするように変更。 選択中の項目は自動スクロールで追従。フッターは常に表示。
- ゴーストテキストを廃止し候補1件でもドロップダウンを表示 - シェルのzsh-autosuggestions との視覚的衝突を解消 - .zshrc wrapper でユーザーの zshrc source 後に ZSH_AUTOSUGGEST_STRATEGY を空にして無効化 - README にシェル履歴サジェスト機能を追記
Supersetターミナル内でzsh-autosuggestionsのサジェスト関数をno-op化し、 ビルトインサジェストとの視覚的な衝突を防止。SUPERSET_DISABLE_ZSH_AUTOSUGGEST 環境変数で制御し、ユーザーの.zshrcは変更しない。
関数のno-opではなくプラグイン公式の_zsh_autosuggest_disable()を使用。 これによりZLEウィジェットバインドが正しく復元され、self-insert ウィジェットチェーンの破損による入力重複を防止。
- ゴーストテキストを完全に廃止し、ドロップダウンUIのみに統一 - 選択中コマンドのフルプレビューを上部に表示(補完部分を緑色で強調) - 候補1件でもドロップダウンを表示 - ↑キーのループを廃止(先頭で止まる) - zsh-autosuggestions無効化を削除(共存可能) - README更新
feat(desktop): シェル履歴サジェスト & Branch PR表示対応
コンフリクト解消: - page.tsx: フォーク独自のkeywordSearch + upstreamのhotkeyOptions変更を統合 - file-types.ts: フォーク独自のSPREADSHEET_EXTENSIONS + upstreamのIMAGE_MIME_TYPE_EXTENSIONSを両方保持 - bun.lock: upstream採用後にbun installで再生成
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (109)
📝 WalkthroughWalkthroughThis PR introduces comprehensive desktop application enhancements including a Chrome extension system with installation/compatibility checking, tab tear-off functionality enabling popup windows, Excel spreadsheet preview with visual diff support, terminal shell history auto-suggestions, AI-generated commit messages, and various UI improvements including tab coloring, zoom controls, file tooltips, and resizable ports list. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related issues
Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
18 issues found across 110 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/desktop/src/main/lib/extensions/crx-downloader.ts">
<violation number="1" location="apps/desktop/src/main/lib/extensions/crx-downloader.ts:148">
P1: ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside `targetDir`.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx:51">
P2: Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.</violation>
</file>
<file name="apps/desktop/src/main/lib/auto-updater.ts">
<violation number="1" location="apps/desktop/src/main/lib/auto-updater.ts:102">
P2: Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts:592">
P2: Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by `sheetN.xml` file index, which can misassociate shapes when sheet order and file numbering differ.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx:95">
P2: `loadLanguageSupport(...)` is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts:36">
P2: Workspace basename extraction uses `split("/")`, which breaks on Windows paths and can render full paths instead of directory names. Use a cross-platform basename helper (e.g., `path.basename`) instead of manual splitting.</violation>
</file>
<file name="apps/desktop/src/lib/trpc/routers/changes/git-operations.ts">
<violation number="1" location="apps/desktop/src/lib/trpc/routers/changes/git-operations.ts:385">
P2: Diff errors are swallowed into null and later treated as new files, which hides failures and can mislabel files in generated summaries. At minimum, log the error and distinguish diff failures from true untracked files.</violation>
</file>
<file name="apps/desktop/src/lib/trpc/routers/changes/file-contents.ts">
<violation number="1" location="apps/desktop/src/lib/trpc/routers/changes/file-contents.ts:81">
P2: Empty catch blocks in readGitFileBinary swallow git/process errors and always return null, which removes diagnostic visibility for unexpected failures.</violation>
</file>
<file name="apps/desktop/src/main/lib/shell-history.ts">
<violation number="1" location="apps/desktop/src/main/lib/shell-history.ts:1">
P3: Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts:249">
P2: Empty catch swallows `executeJavaScript` failures, hiding injection errors and making mouse-nav feature failures non-observable.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetViewer.tsx">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetViewer.tsx:434">
P2: Row headers use the array index instead of the actual Excel row number, which will display incorrect row labels when rows are skipped/hidden/truncated.</violation>
</file>
<file name="apps/desktop/src/main/lib/extensions/compatibility-checker.ts">
<violation number="1" location="apps/desktop/src/main/lib/extensions/compatibility-checker.ts:197">
P2: Empty catch silently skips unreadable JS files, which can hide scan failures and under-report compatibility issues.</violation>
</file>
<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx">
<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx:237">
P2: Inline tab background color overrides the drop-hover background class, so colored tabs won’t show drag-over feedback.</violation>
</file>
<file name="apps/desktop/src/main/lib/browser/browser-manager.ts">
<violation number="1" location="apps/desktop/src/main/lib/browser/browser-manager.ts:149">
P2: Clipboard write errors in context-menu actions are silently swallowed by empty catch blocks, hiding user-visible failures and hindering diagnostics.</violation>
</file>
<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx">
<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx:231">
P2: `QUICK_OPEN` is not gated by `isActive`, so hidden keep-alive workspace pages can still react to the global hotkey.</violation>
</file>
<file name="apps/desktop/src/lib/trpc/routers/tab-tearoff.ts">
<violation number="1" location="apps/desktop/src/lib/trpc/routers/tab-tearoff.ts:18">
P2: `windowId` uses only `Date.now()` (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.</violation>
</file>
<file name="apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts">
<violation number="1" location="apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts:85">
P2: Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.</violation>
</file>
<file name="apps/desktop/src/main/lib/extensions/extension-manager.ts">
<violation number="1" location="apps/desktop/src/main/lib/extensions/extension-manager.ts:42">
P2: Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| const entries = Object.entries(zip.files); | ||
| for (const [relativePath, file] of entries) { | ||
| const fullPath = path.join(targetDir, relativePath); |
There was a problem hiding this comment.
P1: ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside targetDir.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/crx-downloader.ts, line 148:
<comment>ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside `targetDir`.</comment>
<file context>
@@ -0,0 +1,261 @@
+
+ const entries = Object.entries(zip.files);
+ for (const [relativePath, file] of entries) {
+ const fullPath = path.join(targetDir, relativePath);
+
+ if (file.dir) {
</file context>
| document.removeEventListener("mousemove", handleMouseMove); | ||
| document.removeEventListener("mouseup", handleMouseUp); | ||
| }; | ||
| document.addEventListener("mousemove", handleMouseMove); |
There was a problem hiding this comment.
P2: Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx, line 51:
<comment>Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.</comment>
<file context>
@@ -11,10 +18,43 @@ const PORTS_DOCS_URL = `${COMPANY.DOCS_URL}/ports`;
+ document.removeEventListener("mousemove", handleMouseMove);
+ document.removeEventListener("mouseup", handleMouseUp);
+ };
+ document.addEventListener("mousemove", handleMouseMove);
+ document.addEventListener("mouseup", handleMouseUp);
+ },
</file context>
| if (IS_FORK) { | ||
| import("electron") | ||
| .then(({ shell }) => shell.openExternal(FORK_RELEASES_URL)) | ||
| .catch(() => {}); |
There was a problem hiding this comment.
P2: Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/auto-updater.ts, line 102:
<comment>Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.</comment>
<file context>
@@ -86,13 +96,13 @@ export function getUpdateStatus(): AutoUpdateStatusEvent {
+ if (IS_FORK) {
+ import("electron")
+ .then(({ shell }) => shell.openExternal(FORK_RELEASES_URL))
+ .catch(() => {});
emitStatus(AUTO_UPDATE_STATUS.IDLE);
return;
</file context>
| .catch(() => {}); | |
| .catch((error) => { | |
| console.warn("[auto-updater:fork] Failed to open releases page:", error); | |
| }); |
| sheetIndex++; | ||
| const dims = getSheetDimensions(worksheet); | ||
| const mergeMap = buildMergeMap(worksheet); | ||
| const shapes = drawingsMap.get(sheetIndex) || []; |
There was a problem hiding this comment.
P2: Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by sheetN.xml file index, which can misassociate shapes when sheet order and file numbering differ.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts, line 592:
<comment>Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by `sheetN.xml` file index, which can misassociate shapes when sheet order and file numbering differ.</comment>
<file context>
@@ -0,0 +1,685 @@
+ sheetIndex++;
+ const dims = getSheetDimensions(worksheet);
+ const mergeMap = buildMergeMap(worksheet);
+ const shapes = drawingsMap.get(sheetIndex) || [];
+ const colCount = dims.maxC - dims.minC + 1;
+ const columnWidths: number[] = [];
</file context>
|
|
||
| mergeViewRef.current = mergeView; | ||
|
|
||
| void loadLanguageSupport(language).then((ext) => { |
There was a problem hiding this comment.
P2: loadLanguageSupport(...) is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx, line 95:
<comment>`loadLanguageSupport(...)` is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.</comment>
<file context>
@@ -0,0 +1,132 @@
+
+ mergeViewRef.current = mergeView;
+
+ void loadLanguageSupport(language).then((ext) => {
+ if (!ext || !mergeViewRef.current) return;
+ const mv = mergeViewRef.current;
</file context>
| @@ -1,5 +1,11 @@ | |||
| import type { ExternalApp } from "@superset/local-db"; | |||
There was a problem hiding this comment.
P2: QUICK_OPEN is not gated by isActive, so hidden keep-alive workspace pages can still react to the global hotkey.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx, line 231:
<comment>`QUICK_OPEN` is not gated by `isActive`, so hidden keep-alive workspace pages can still react to the global hotkey.</comment>
<file context>
@@ -209,11 +228,12 @@ function WorkspacePage() {
);
- useAppHotkey("NEW_GROUP", () => addTab(workspaceId), undefined, [
+ const hotkeyOptions = { enabled: isActive };
+ useAppHotkey("NEW_GROUP", () => addTab(workspaceId), hotkeyOptions, [
workspaceId,
</file context>
| }), | ||
| ) | ||
| .mutation(({ input }) => { | ||
| const windowId = `tearoff-${Date.now()}`; |
There was a problem hiding this comment.
P2: windowId uses only Date.now() (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/lib/trpc/routers/tab-tearoff.ts, line 18:
<comment>`windowId` uses only `Date.now()` (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.</comment>
<file context>
@@ -0,0 +1,36 @@
+ }),
+ )
+ .mutation(({ input }) => {
+ const windowId = `tearoff-${Date.now()}`;
+
+ // Store data FIRST so it's available when preload requests it
</file context>
| } | ||
|
|
||
| return net.fetch(pathToFileURL(iconPath).toString()); | ||
| } catch { |
There was a problem hiding this comment.
P2: Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts, line 85:
<comment>Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.</comment>
<file context>
@@ -0,0 +1,89 @@
+ }
+
+ return net.fetch(pathToFileURL(iconPath).toString());
+ } catch {
+ return new Response("Internal error", { status: 500 });
+ }
</file context>
| try { | ||
| const data = await readFile(storePath, "utf-8"); | ||
| return JSON.parse(data) as ExtensionStore; | ||
| } catch { |
There was a problem hiding this comment.
P2: Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/extension-manager.ts, line 42:
<comment>Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.</comment>
<file context>
@@ -0,0 +1,339 @@
+ try {
+ const data = await readFile(storePath, "utf-8");
+ return JSON.parse(data) as ExtensionStore;
+ } catch {
+ return { extensions: [] };
+ }
</file context>
| @@ -0,0 +1,105 @@ | |||
| import { constants } from "node:fs"; | |||
There was a problem hiding this comment.
P3: Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/shell-history.ts:
<comment>Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.</comment>
<file context>
@@ -0,0 +1,105 @@
+import { constants } from "node:fs";
+import { access, readFile } from "node:fs/promises";
+import { homedir } from "node:os";
+
+let cachedHistory: string[] | null = null;
+let lastReadTime = 0;
+const CACHE_TTL_MS = 30_000;
+
+function parseZshHistory(content: string): string[] {
</file context>
Summary
コンフリクト解消
page.tsx: フォーク独自の keywordSearch + upstream の hotkeyOptions 変更を統合file-types.ts: フォーク独自の SPREADSHEET_EXTENSIONS + upstream の IMAGE_MIME_TYPE_EXTENSIONS を両方保持bun.lock: upstream 採用後に bun install で再生成Summary by cubic
Merged upstream/main (14 commits) and shipped major desktop upgrades: spreadsheet viewing/diff, persistent browser tabs, pane pop‑out, terminal history suggestions, Chrome extension support, and a fork-aware updater.
New Features
exceljs,jszip, anddiff. Large text diffs use@codemirror/merge.ports.jsonentries, always show static ports, improved workspace labels, and optional file path tooltips.Bug Fixes
Written for commit aabe193. Summary will update on new commits.
Summary by CodeRabbit
New Features
Documentation