Walkthrough
Adds an "open in editor" feature: new EDITORS and EditorId types, IPC_CHANNELS.shellOpenInEditor plus main-process handler, nativeApi.shell.openInEditor in preload, and renderer UI/shortcut to invoke and persist the chosen editor.
Changes
| Cohort / File(s) | Summary |
|---|---|
Main / IPC handler apps/desktop/src/main.ts | Imports shell and EDITORS; registers IPC_CHANNELS.shellOpenInEditor handler that looks up editor by id, throws on unknown, uses shell.openPath(cwd) for file-manager or spawn (detached, stdio ignored) and unref() for editor commands. |
Preload / Renderer bridge apps/desktop/src/preload.ts | Adds nativeApi.shell.openInEditor(cwd: string, editor: EditorId) which invokes IPC_CHANNELS.shellOpenInEditor via ipcRenderer.invoke. |
Renderer UI apps/renderer/src/components/ChatView.tsx | Adds editor dropdown, isEditorMenuOpen and lastEditor state with localStorage persistence, outside-click handling, Cmd/Ctrl+O shortcut to open last editor, and calls api.shell.openInEditor. |
Contracts / Types packages/contracts/src/ipc.ts | Exports new EDITORS array and EditorId type, adds IPC_CHANNELS.shellOpenInEditor, and extends NativeApi with shell.openInEditor(cwd: string, editor: EditorId): Promise<void>. |
Manifests / Package manifest_file, package.json | Small manifest/package updates referenced by diff (lines changed +25/-1 and +4/-0 respectively). |
Sequence Diagram
| 1 | sequenceDiagram |
| 2 | actor User |
| 3 | participant ChatView as Renderer (ChatView.tsx) |
| 4 | participant Preload as Preload (preload.ts) |
| 5 | participant Main as Main Process (main.ts) |
| 6 | participant OS as Operating System Shell |
| 7 | |
| 8 | User->>ChatView: Click "Open in…" or press Cmd/Ctrl+O |
| 9 | ChatView->>ChatView: openInEditor(editorId) and persist lastEditor |
| 10 | ChatView->>Preload: invoke 'shell:open-in-editor' (cwd, editorId) |
| 11 | Preload->>Main: Forward IPC invoke |
| 12 | Main->>Main: Lookup editor in EDITORS |
| 13 | alt editor == 'file-manager' |
| 14 | Main->>OS: shell.openPath(cwd) |
| 15 | else editor has command |
| 16 | Main->>OS: spawn(editorCommand, [cwd], {detached, stdio:'ignore'}) and unref() |
| 17 | end |
| 18 | OS-->>Main: process/path opened |
| 19 | Main-->>Preload: resolve Promise<void> |
| 20 | Preload-->>ChatView: invoke resolves |
| 21 | ChatView->>ChatView: close editor menu |
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately summarizes the main feature added: an open-in-editor capability triggered by a Cmd+O keyboard shortcut, which is the primary change across all modified files. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing touches
- 📝 Generate docstrings
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
juliusmarminge/open-in-editor
No actionable comments were generated in the recent review. 🎉
🧹 Recent nitpick comments
apps/renderer/src/components/ChatView.tsx (3)
36-40:navigator.platformis deprecated but acceptable here.While
navigator.platformis technically deprecated in favor ofnavigator.userAgentData, it remains well-supported in Electron's renderer process. This is a reasonable choice for platform detection in this context.
203-220: Consider extracting click-outside logic to a reusable hook.This pattern is duplicated with the model menu handler (lines 184-201). A
useOnClickOutside(ref, callback)hook would reduce duplication.♻️ Example hook extraction
typescript
1 function useOnClickOutside( 2 ref: React.RefObject<HTMLElement>, 3 handler: () => void, 4 enabled: boolean, 5 ) { 6 useEffect(() => { 7 if (!enabled) return; 8 const handleClickOutside = (event: MouseEvent) => { 9 if ( 10 ref.current && 11 event.target instanceof Node && 12 !ref.current.contains(event.target) 13 ) { 14 handler(); 15 } 16 }; 17 window.addEventListener("mousedown", handleClickOutside); 18 return () => window.removeEventListener("mousedown", handleClickOutside); 19 }, [ref, handler, enabled]); 20 } Then use:
typescript
1 useOnClickOutside(editorMenuRef, () => setIsEditorMenuOpen(false), isEditorMenuOpen); 2 useOnClickOutside(modelMenuRef, () => setIsModelMenuOpen(false), isModelMenuOpen);
378-410: Add aria attributes for accessibility.The dropdown trigger is missing
aria-expandedandaria-haspopupattributes that improve screen reader experience.♿ Suggested accessibility improvement
diff
1 <button 2 type="button" 3 className="rounded-md px-2 py-1 text-[10px] text-[`#a0a0a0`]/40 transition-colors duration-150 hover:text-[`#a0a0a0`]/60" 4 onClick={() => setIsEditorMenuOpen((v) => !v)} 5 + aria-expanded={isEditorMenuOpen} 6 + aria-haspopup="menu" 7 > 8 Open in… 9 </button>
Comment @coderabbitai help to get the list of available commands and usage tips.