Skip to content

feat(desktop): add right-click context menu to file editor with Monaco actions#631

Merged
Kitenite merged 3 commits into
mainfrom
file-editor-right-click
Jan 7, 2026
Merged

feat(desktop): add right-click context menu to file editor with Monaco actions#631
Kitenite merged 3 commits into
mainfrom
file-editor-right-click

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 6, 2026

Summary

  • Add custom right-click context menu to the file editor (raw and diff views) that combines Monaco editor actions with pane management features from terminal panes
  • Create shared EditorContextMenu component for reuse across editor types

Features

Monaco Editor Actions:

  • Go to Definition, Go to References, Go to Symbol
  • Peek Definition, Peek References (submenu)
  • Rename Symbol, Change All Occurrences, Format Document
  • Cut, Copy, Paste, Select All
  • Copy Path, Copy Path:Line
  • Find, Command Palette

Pane Management (matching terminal panes):

  • Split Horizontally / Vertically
  • Move to Tab (with submenu)
  • Close File

Summary by CodeRabbit

  • New Features

    • Custom editor context menu with clipboard, selection, find, change-all-occurrences, copy-path (with line), pane controls (split horizontally/vertically, move to tab/new tab, close) and platform-aware shortcuts.
    • Context menu support added to file and diff views; native editor context menu is disabled when custom menu is active.
    • Editors can be wrapped to wire editor and pane actions.
  • Chores

    • Public exports added for the context menu, editor actions hook, and related utilities.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 6, 2026

Warning

Rate limit exceeded

@Kitenite has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 17 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 27977e9 and d4db5b4.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
📝 Walkthrough

Walkthrough

Introduces a pluggable editor context‑menu system and integrates it into diff and file editors: adds EditorContextMenu, FileEditorContextMenu, useEditorActions, editor action registration (copy path:line), and propagates pane/tab split and move handlers to file viewer panes.

Changes

Cohort / File(s) Summary
EditorContextMenu core & exports
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx, .../EditorContextMenu/index.ts, .../components/index.ts
New EditorContextMenu component and exported types (EditorActions, PaneActions); renders clipboard/editor/pane actions and dynamic Move‑to‑Tab submenu; consolidated re-exports.
Editor actions & hook
.../EditorContextMenu/editor-actions.ts, .../EditorContextMenu/useEditorActions.ts
New registerCopyPathLineAction and useEditorActions hook that expose Monaco action handlers (cut/copy/paste/selectAll/find/copyPath/copyPathWithLine/changeAllOccurrences) for use by context menus.
FileEditorContextMenu wrapper
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx, .../FileEditorContextMenu/index.ts
New wrapper component that derives the Monaco editor instance, builds editorActions via useEditorActions, constructs paneActions, and renders children inside EditorContextMenu.
DiffViewer integration
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
Adds DiffViewerContextMenuProps and optional contextMenuProps to DiffViewerProps; conditionally wraps diff editor with EditorContextMenu and disables Monaco native context menu when custom menu is provided.
FileViewerContent — menu wiring & editor lifecycle
.../FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
Passes pane/tab props and contextMenuProps to editors, wraps main editor with FileEditorContextMenu, disables Monaco native context menu, and registers copy‑path action on mount.
Pane / Tab prop propagation
.../TabView/FileViewerPane/FileViewerPane.tsx, .../TabView/index.tsx
Extends FileViewerPane and TabView interfaces with split handlers and tab movement props (splitPaneHorizontal, splitPaneVertical, availableTabs, onMoveToTab, onMoveToNewTab) and propagates them into child panes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Monaco as Monaco Editor
    participant FileWrap as FileEditorContextMenu
    participant Menu as EditorContextMenu
    participant PaneCtrl as Pane Controller

    Note over Monaco,FileWrap: Monaco native context menu disabled when custom menu is provided
    User->>Monaco: Right-click in editor
    Monaco->>FileWrap: emit contextmenu event
    FileWrap->>Menu: open menu with editorActions & paneActions
    Menu->>User: display custom context menu

    alt Copy Path:Line
      User->>Menu: Select "Copy Path:Line"
      Menu->>FileWrap: invoke onCopyPathWithLine
      FileWrap->>Monaco: query selection / position
      FileWrap->>FileWrap: format "path:startLine:startCol"
      FileWrap->>User: copy formatted string to clipboard
    end

    alt Split Pane Horizontal
      User->>Menu: Select "Split Horizontally"
      Menu->>FileWrap: invoke onSplitHorizontal
      FileWrap->>PaneCtrl: splitPaneHorizontal(tabId, sourcePaneId, path?)
      PaneCtrl->>PaneCtrl: create new pane and update layout
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through code to make right‑clicks bright,

Menus that pop with actions, neat and light.
Paths and lines, split panes that roam,
Monaco bowed out — the rabbit made a home.
🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The description clearly outlines the changes (custom context menu for file editor with Monaco actions and pane management) and lists specific features, but does not follow the provided template structure with required sections. Reorganize the description to match the template structure by explicitly including sections for Type of Change, Testing, and Related Issues with appropriate content.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a right-click context menu to the file editor with Monaco actions, which is the primary objective across all modified files.

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.

Actionable comments posted: 1

🧹 Nitpick comments (7)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx (2)

31-162: Consider extracting a helper to reduce repetition in editor action handlers.

All Monaco trigger handlers follow the same pattern: null-check editor, focus, trigger action. This could be DRY'd with a helper function.

🔎 Suggested helper extraction
+const triggerEditorAction = (
+	editorRef: MutableRefObject<Monaco.editor.IStandaloneCodeEditor | null>,
+	actionId: string,
+) => {
+	const editor = editorRef.current;
+	if (!editor) return;
+	editor.focus();
+	editor.trigger("contextMenu", actionId, null);
+};

 const handleCut = () => {
-	const editor = editorRef.current;
-	if (!editor) return;
-	editor.focus();
-	editor.trigger("contextMenu", "editor.action.clipboardCutAction", null);
+	triggerEditorAction(editorRef, "editor.action.clipboardCutAction");
 };

This pattern can then be applied to all other trigger-based handlers.


63-87: Clipboard write operations silently ignore failures.

navigator.clipboard.writeText returns a Promise that may reject. Consider adding error handling or using Electron's clipboard API for more reliability.

🔎 Example with error handling
 const handleCopyPath = () => {
-	navigator.clipboard.writeText(filePath);
+	navigator.clipboard.writeText(filePath).catch((err) => {
+		console.error("[FileEditorContextMenu/copyPath] Failed to copy:", err);
+	});
 };
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx (1)

121-123: Inline arrow functions create new references on each render.

The onMoveToTab and onMoveToNewTab callbacks are recreated on every render since they're defined inline. If FileViewerPane or TabPane perform any memoization based on props, this would defeat it.

🔎 Consider using useCallback if this causes performance issues
// If needed, memoize these at the component level
const handleMoveToTab = useCallback(
  (paneId: string, targetTabId: string) => movePaneToTab(paneId, targetTabId),
  [movePaneToTab]
);

// Then in renderPane:
onMoveToTab={(targetTabId) => handleMoveToTab(paneId, targetTabId)}

However, since renderPane itself is already memoized with useCallback, the current approach is acceptable unless profiling shows issues.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (2)

158-207: Code duplication with FileEditorContextMenu action handlers.

The handleCopy, handleSelectAll, handleCopyPath, handleCopyPathWithLine, and handleFind handlers are nearly identical to those in FileEditorContextMenu.tsx. Consider extracting shared utilities to reduce duplication.

🔎 Suggested approach

Extract common clipboard and editor action helpers to a shared utility module:

// e.g., in a shared editor-actions.ts utility
export function copyPathToClipboard(filePath: string) {
  navigator.clipboard.writeText(filePath);
}

export function copyPathWithLineToClipboard(
  filePath: string,
  selection: Monaco.Selection | null
) {
  if (!selection) {
    navigator.clipboard.writeText(filePath);
    return;
  }
  const { startLineNumber, endLineNumber } = selection;
  const pathWithLine =
    startLineNumber === endLineNumber
      ? `${filePath}:${startLineNumber}`
      : `${filePath}:${startLineNumber}-${endLineNumber}`;
  navigator.clipboard.writeText(pathWithLine);
}

Both FileEditorContextMenu and DiffViewer can then use these shared helpers.


250-258: Consider using shorthand property syntax.

The paneActions object could use shorthand syntax since the property names match the contextMenuProps properties.

🔎 Shorthand alternative
-	const paneActions: PaneActions = {
-		onSplitHorizontal: contextMenuProps.onSplitHorizontal,
-		onSplitVertical: contextMenuProps.onSplitVertical,
-		onClosePane: contextMenuProps.onClosePane,
-		currentTabId: contextMenuProps.currentTabId,
-		availableTabs: contextMenuProps.availableTabs,
-		onMoveToTab: contextMenuProps.onMoveToTab,
-		onMoveToNewTab: contextMenuProps.onMoveToNewTab,
-	};
+	const paneActions: PaneActions = { ...contextMenuProps };

This works since DiffViewerContextMenuProps matches PaneActions exactly.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx (1)

41-67: Consider grouping related props to reduce interface complexity.

The FileViewerContentProps interface now has 24 properties. While this follows the object params guideline, grouping related props could improve readability and maintainability.

🔎 Suggested grouping
interface ContextMenuProps {
  onSplitHorizontal: () => void;
  onSplitVertical: () => void;
  onClosePane: () => void;
  currentTabId: string;
  availableTabs: Tab[];
  onMoveToTab: (tabId: string) => void;
  onMoveToNewTab: () => void;
}

interface FileViewerContentProps {
  // ... existing props ...
  contextMenuProps: ContextMenuProps;
}

This would also align with how DiffViewer accepts contextMenuProps.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (1)

81-84: Consider using Electron's platform detection instead of deprecated navigator.platform.

The navigator.platform API is deprecated. Since this is an Electron desktop app, consider using process.platform from Node.js via the main process, or check if the platform information is already available through your app's context.

Alternative approaches

Option 1: Use process.platform via tRPC (preferred for Electron)

// In main process tRPC router
getPlatform: publicProcedure.query(() => {
  return process.platform;
});

// In component
const { data: platform } = trpc.getPlatform.useQuery();
const isMac = platform === 'darwin';

Option 2: Use userAgent (browser fallback)

-const isMac =
-  typeof navigator !== "undefined" &&
-  navigator.platform.toLowerCase().includes("mac");
+const isMac =
+  typeof navigator !== "undefined" &&
+  /Mac|iPhone|iPad|iPod/.test(navigator.userAgent);

As per coding guidelines, Electron IPC should use tRPC as defined in src/lib/trpc.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 745da62 and 92c9b47.

📒 Files selected for processing (9)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
🧠 Learnings (3)
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/*/src/components/**/*.{ts,tsx} : Co-locate component dependencies: utils, hooks, constants, config, tests, stories in the same folder as the component using them

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/*/src/components/{ui,ai-elements,react-flow}/*.tsx : Use kebab-case single files for shadcn/ui components (e.g., button.tsx, base-node.tsx) in src/components/ui/, src/components/ai-elements, and src/components/react-flow/

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
🧬 Code graph analysis (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx (1)
  • FileEditorContextMenu (19-197)
apps/desktop/src/shared/detect-language.ts (1)
  • detectLanguage (1-61)
apps/desktop/src/renderer/contexts/MonacoProvider.tsx (1)
  • MONACO_EDITOR_OPTIONS (107-120)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (1)
packages/ui/src/components/ui/context-menu.tsx (9)
  • ContextMenu (237-237)
  • ContextMenuTrigger (238-238)
  • ContextMenuContent (239-239)
  • ContextMenuItem (240-240)
  • ContextMenuShortcut (245-245)
  • ContextMenuSub (248-248)
  • ContextMenuSubTrigger (250-250)
  • ContextMenuSubContent (249-249)
  • ContextMenuSeparator (244-244)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx (1)
apps/desktop/src/renderer/stores/tabs/actions/move-pane.ts (2)
  • movePaneToTab (21-77)
  • movePaneToNewTab (79-137)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (12)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts (1)

1-1: LGTM!

Clean re-export for the FileEditorContextMenu component.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts (1)

1-2: LGTM!

Clean re-exports with proper export type for type-only exports.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts (1)

1-2: LGTM!

Properly exposes EditorContextMenu and its types from the shared components surface.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx (1)

164-196: LGTM!

Clean composition of EditorContextMenu with all editor and pane actions properly wired.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx (1)

44-47: LGTM on workspace tabs filtering.

The workspaceTabs filter correctly scopes available tabs to the current workspace for move-to-tab functionality.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (1)

239-242: Good: Monaco context menu correctly disabled when custom menu is active.

The contextmenu: !contextMenuProps option properly disables Monaco's native context menu only when the custom context menu is provided.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx (2)

242-274: LGTM!

Clean integration of FileEditorContextMenu wrapper around the Monaco Editor with all props correctly forwarded and native context menu properly disabled.


185-194: LGTM!

Context menu props correctly forwarded to DiffViewer for consistent context menu behavior across both raw and diff views.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (3)

36-70: LGTM! Well-designed interfaces with appropriate optional/required properties.

The interfaces provide good flexibility with onCopy as a required baseline action and other editor actions as optional, allowing the component to adapt to different editor contexts.


265-303: LGTM! Well-structured pane management actions with good UX considerations.

The pane actions section is well-implemented:

  • Conditional separator (line 289) improves visual clarity
  • "New Tab" is always available even when no other tabs exist
  • Destructive variant appropriately applied to "Close File"
  • Proper key prop on mapped tab items

119-261: Verify that displayed keyboard shortcuts match Monaco editor's actual keybindings and resolve shortcut conflicts.

The menu displays keyboard shortcuts that conflict with or diverge from Monaco's defaults. Go to Definition shows Cmd+F12 but Monaco's actual default is F12 (without modifier). Additionally, Shift+F12 is used for both Go to References (line 130) and Peek References (line 160), creating a conflict. Other shortcuts like Go to Symbol (Cmd+Shift+O) and Change All Occurrences (Cmd+F2) also lack equivalent Monaco defaults. Verify all displayed shortcuts match Monaco's actual behavior, align with the application's actual keybindings, and resolve the duplicate Shift+F12 assignment.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx (1)

312-314: No action needed. The inline arrow functions are appropriate for this use case.

FileViewerContent is not memoized with React.memo, so the inline arrow functions at lines 312-314 create no performance issues. Without memoization, callback reference changes have no impact on component re-renders.

Likely an incorrect or invalid review comment.

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.

Actionable comments posted: 1

🤖 Fix all issues with AI Agents
In
@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx:
- Around line 81-84: Replace the deprecated navigator.platform logic in
EditorContextMenu: remove the navigator.platform checks and instead call
trpc.window.getPlatform.useQuery() (e.g., const { data: platform } =
trpc.window.getPlatform.useQuery()), then compute isMac as platform === "darwin"
and derive cmdKey from isMac; ensure you replace references to the old isMac and
cmdKey variables and remove any navigator.platform usage.
🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (1)

56-64: Consider renaming to reflect mixed data and action properties.

The PaneActions interface contains both action callbacks (onSplitHorizontal, etc.) and data properties (currentTabId, availableTabs). Consider renaming to PaneActionsProps or splitting into separate interfaces for clarity.

🔎 Alternative structure
-export interface PaneActions {
+export interface PaneActionsProps {
 	onSplitHorizontal: () => void;
 	onSplitVertical: () => void;
 	onClosePane: () => void;
 	currentTabId: string;
 	availableTabs: Tab[];
 	onMoveToTab: (tabId: string) => void;
 	onMoveToNewTab: () => void;
 }

Or split into separate interfaces:

export interface PaneData {
	currentTabId: string;
	availableTabs: Tab[];
}

export interface PaneActions {
	onSplitHorizontal: () => void;
	onSplitVertical: () => void;
	onClosePane: () => void;
	onMoveToTab: (tabId: string) => void;
	onMoveToNewTab: () => void;
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92c9b47 and 9d32fa5.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (3)

104-104: Review: Cut and Paste visibility are coupled.

The showCutPaste flag requires both onCut and onPaste to be available. This means if only one is provided, neither will be shown. This is likely intentional for UI consistency, but verify this matches the desired behavior.

Also applies to: 198-229


72-302: Well-structured component with good conditional rendering.

The component implementation is clean and follows best practices:

  • Proper conditional rendering prevents empty menu sections
  • Tab filtering logic correctly excludes the current tab
  • Consistent icon usage and keyboard shortcut display
  • Type-safe implementation with no any types
  • Follows coding guidelines (no Node.js imports, single component per file)

127-131: No action needed - shortcuts correctly reflect Monaco's default behavior.

The keyboard shortcuts are correct as displayed. Monaco editor and VS Code both use Shift+F12 as the default shortcut for both "Go to References" and "Peek References" actions. This is intentional, not a duplicate or error.

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.

Actionable comments posted: 1

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/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts (1)

10-33: Add error handling for clipboard operations.

The navigator.clipboard.writeText() call can fail due to permissions, security context, or browser compatibility issues. Silent failures will leave users confused when the copy action appears to do nothing.

🔎 Proposed fix with error handling
 export function registerCopyPathLineAction(
 	editor: Monaco.editor.IStandaloneCodeEditor,
 	filePath: string,
 ) {
 	editor.addAction({
 		id: "copy-path-line",
 		label: "Copy Path:Line",
 		keybindings: [
 			monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KeyC,
 		],
-		run: (ed) => {
+		run: async (ed) => {
 			const selection = ed.getSelection();
 			if (!selection) return;
 
 			const { startLineNumber, endLineNumber } = selection;
 			const pathWithLine =
 				startLineNumber === endLineNumber
 					? `${filePath}:${startLineNumber}`
 					: `${filePath}:${startLineNumber}-${endLineNumber}`;
 
-			navigator.clipboard.writeText(pathWithLine);
+			try {
+				await navigator.clipboard.writeText(pathWithLine);
+			} catch (error) {
+				console.error("[editor-actions/copy-path-line] Failed to copy to clipboard:", error);
+			}
 		},
 	});
 }

As per coding guidelines: "Never swallow errors silently - at minimum log them with context."

🤖 Fix all issues with AI Agents
In
@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts:
- Around line 53-77: Wrap every navigator.clipboard.writeText call in
handleCopyPath and handleCopyPathWithLine in a try/catch and log any caught
error with context (include the function name and the value attempted to copy,
e.g., filePath or pathWithLine); for handleCopyPathWithLine also log when editor
or selection is missing before returning. Use the existing console/error logging
mechanism (e.g., console.error) to record the error and the attempted text so
failures aren’t swallowed.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d32fa5 and 5556789.

📒 Files selected for processing (7)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
🧠 Learnings (1)
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts (1)
  • registerCopyPathLineAction (3-3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx (1)
  • FileEditorContextMenu (19-55)
apps/desktop/src/shared/detect-language.ts (1)
  • detectLanguage (1-61)
apps/desktop/src/renderer/contexts/MonacoProvider.tsx (1)
  • MONACO_EDITOR_OPTIONS (107-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (6)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts (1)

1-2: LGTM - Clean public API surface.

The re-exports provide a clean component boundary for the EditorContextMenu module. This is an appropriate use of barrel files for defining public API surfaces.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts (1)

16-171: Well-structured hook with consistent patterns.

The hook is well-designed with:

  • Proper use of useCallback for memoization
  • Consistent pattern across all handlers (get editor → check → focus → trigger)
  • Clean separation between clipboard, navigation, and editing actions
  • Correct conditional inclusion of cut/paste based on editable flag
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (2)

154-165: Good editor selection and action configuration.

The getEditor fallback logic correctly prioritizes the modified editor (where users typically make changes) and falls back to the original editor. Setting editable: false for useEditorActions is appropriate since diff viewers are read-only contexts where cut/paste operations should be handled by the underlying modified editor, not the diff viewer wrapper.


176-222: Clean conditional rendering with proper Monaco context menu handling.

The implementation correctly:

  • Extracts the diffEditor JSX for reuse in both paths
  • Disables Monaco's native context menu when contextMenuProps is provided (line 197)
  • Uses early return pattern to avoid unnecessary nesting (lines 203-205)
  • Wraps with EditorContextMenu only when context menu props are supplied
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx (2)

110-128: Correct editor initialization with copy-path action.

The handleEditorMount callback properly registers both save and copy-path actions, and the dependency array correctly includes filePath to ensure the copy-path action updates when the file changes.


250-284: Proper context menu integration with Monaco native menu disabled.

The editor is correctly wrapped with FileEditorContextMenu and Monaco's native context menu is properly disabled via contextmenu: false (line 279) to prevent conflicts with the custom menu system.

- Add EditorContextMenu component with clipboard, file, and pane actions
- Support Cut, Copy, Paste, Copy Path, Copy Path:Line
- Add Change All Occurrences, Select All, Find actions
- Include Split Horizontally/Vertically and Move to Tab options
- Apply context menu to both file editor and diff viewer
- Extract shared useEditorActions hook for reusability
- Disable Monaco's native context menu when custom menu is active
@Kitenite Kitenite force-pushed the file-editor-right-click branch from 5556789 to 8329148 Compare January 7, 2026 00:51
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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx:
- Around line 66-69: Replace the deprecated navigator.platform check in
EditorContextMenu with the app's tRPC window service: call the exposed platform
detection method (e.g. window.trpc.platform.isMac() or the equivalent used in
TopBar/StartTopBar) to set isMac, then derive cmdKey from that value and update
any surrounding logic to await or handle the service call if it’s asynchronous;
ensure you remove navigator.platform usage and mirror the same API shape the
other components use.
🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (1)

208-216: Consider simplifying the paneActions mapping.

The paneActions object is currently created by manually mapping each property from contextMenuProps. Since DiffViewerContextMenuProps and PaneActions have identical structure, this can be simplified.

🔎 Suggested simplification
-	const paneActions: PaneActions = {
-		onSplitHorizontal: contextMenuProps.onSplitHorizontal,
-		onSplitVertical: contextMenuProps.onSplitVertical,
-		onClosePane: contextMenuProps.onClosePane,
-		currentTabId: contextMenuProps.currentTabId,
-		availableTabs: contextMenuProps.availableTabs,
-		onMoveToTab: contextMenuProps.onMoveToTab,
-		onMoveToNewTab: contextMenuProps.onMoveToNewTab,
-	};
+	const paneActions: PaneActions = contextMenuProps;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5556789 and 8329148.

📒 Files selected for processing (11)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/useEditorActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/editor-actions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/FileEditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileEditorContextMenu/index.ts
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/index.ts
🧠 Learnings (3)
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/*/src/components/{ui,ai-elements,react-flow}/*.tsx : Use kebab-case single files for shadcn/ui components (e.g., button.tsx, base-node.tsx) in src/components/ui/, src/components/ai-elements, and src/components/react-flow/

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/*/src/components/**/*.{ts,tsx} : Co-locate component dependencies: utils, hooks, constants, config, tests, stories in the same folder as the component using them

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/index.ts
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (1)
packages/ui/src/components/ui/context-menu.tsx (9)
  • ContextMenu (237-237)
  • ContextMenuTrigger (238-238)
  • ContextMenuContent (239-239)
  • ContextMenuItem (240-240)
  • ContextMenuShortcut (245-245)
  • ContextMenuSeparator (244-244)
  • ContextMenuSub (248-248)
  • ContextMenuSubTrigger (250-250)
  • ContextMenuSubContent (249-249)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (2)

154-165: LGTM! Clean integration of editor actions.

The getEditor callback correctly prioritizes the modified editor and falls back to the original editor, and the useEditorActions hook is properly configured with editable: false for the diff viewer's read-only context.


197-197: LGTM! Correctly disables Monaco's native menu.

The contextmenu option correctly disables Monaco's built-in context menu when custom context menu props are provided, preventing conflicting menus.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/EditorContextMenu/EditorContextMenu.tsx (2)

30-49: LGTM! Well-structured interface definitions.

The EditorActions and PaneActions interfaces have clear separation of concerns. The required vs. optional distinction in EditorActions (e.g., onCopy required but onCut/onPaste optional) correctly reflects read-only contexts where clipboard modifications may not apply.


84-188: LGTM! Clean menu structure with good UX patterns.

The context menu implementation has well-organized sections (clipboard, editor, pane actions) with appropriate conditional rendering. The targetTabs filtering correctly excludes the current tab, and the keyboard shortcuts match platform conventions using the computed cmdKey.

@Kitenite Kitenite merged commit 38985f7 into main Jan 7, 2026
5 checks passed
@Kitenite Kitenite deleted the file-editor-right-click branch January 7, 2026 01:01
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 7, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

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.

1 participant