Repository navigation
feat(desktop): add JetBrains IDEs submenu to Open button - #277
Conversation
Add a JetBrains submenu under the Open dropdown that includes all major JetBrains IDEs: IntelliJ IDEA, WebStorm, PyCharm, PhpStorm, RubyMine, GoLand, CLion, Rider, DataGrip, AppCode, Fleet, and RustRover. Uses react-icons/si for JetBrains icons instead of custom assets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds twelve JetBrains IDEs as supported external apps: registers them in the desktop schema, adds router branches returning native open commands, and exposes them in the renderer's OpenInButton via a JetBrains submenu and expanded app option/icon handling. (50 words) Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (1)
127-128: Hardcoded array index for fallback is fragile.The fallback
APP_OPTIONS[1]relies on array ordering. IfAPP_OPTIONSis reordered, this could silently return an unexpected default.Consider using a named constant or finding by ID:
-const getAppOption = (id: ExternalApp) => - ALL_APP_OPTIONS.find((app) => app.id === id) ?? APP_OPTIONS[1]; +const DEFAULT_APP_OPTION = APP_OPTIONS.find((app) => app.id === "cursor") ?? APP_OPTIONS[0]; + +const getAppOption = (id: ExternalApp) => + ALL_APP_OPTIONS.find((app) => app.id === id) ?? DEFAULT_APP_OPTION;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/desktop/src/lib/trpc/routers/external/index.ts(1 hunks)apps/desktop/src/main/lib/db/schemas.ts(1 hunks)apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx(4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/main/lib/db/schemas.tsapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/main/lib/db/schemas.tsapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Avoidanytype in TypeScript unless absolutely necessary
Files:
apps/desktop/src/main/lib/db/schemas.tsapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/src/{main,renderer,shared}/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use type-safe IPC system for communication between Electron main and renderer processes
Files:
apps/desktop/src/main/lib/db/schemas.ts
**/{components,pages}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
**/{components,pages}/**/*.tsx: Use one folder per component with structureComponentName/ComponentName.tsxplusindex.tsfor barrel export
Create one component per file - do not use multi-component files
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/src/{renderer,shared,preload}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in renderer process code or shared code in the desktop app
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
🧠 Learnings (2)
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Please use alias as defined in `tsconfig.json` when possible
Applied to files:
apps/desktop/src/main/lib/db/schemas.tsapps/desktop/src/lib/trpc/routers/external/index.ts
📚 Learning: 2025-12-06T18:44:13.290Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T18:44:13.290Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Shadcn/ui components in `src/components/ui/`, `src/components/ai-elements`, and `src/components/react-flow/` use kebab-case single files (e.g., `button.tsx`) for shadcn CLI compatibility
Applied to files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (2)
apps/desktop/src/main/lib/db/schemas.ts (1)
ExternalApp(96-96)packages/ui/src/components/dropdown-menu.tsx (4)
DropdownMenuItem(251-251)DropdownMenuSub(257-257)DropdownMenuSubTrigger(258-258)DropdownMenuSubContent(259-259)
⏰ 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/main/lib/db/schemas.ts (1)
81-93: LGTM! Clean extension of the EXTERNAL_APPS constant.The JetBrains IDE identifiers follow the existing naming convention (lowercase, single-word) and are properly grouped with a comment. The derived
ExternalApptype will automatically include these new values.apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (5)
8-30: Imports are well-organized.The new imports for dropdown sub-menu components,
ComponentType, and JetBrains icons are appropriate. The type-only import frommain/lib/db/schemas(line 14) is acceptable since it only imports a type and doesn't pull in Node.js runtime code.
41-55: Good use of discriminated union for icon types.The
iconTypediscriminator enables type-safe handling when rendering different icon formats. This is a clean pattern for supporting both image URLs and React components.
73-123: JETBRAINS_OPTIONS array is well-structured.The fallback to
SiJetbrainsfor AppCode, Fleet, and RustRover (with explanatory comment) is a reasonable approach when specific icons aren't available. All IDs correctly align with the schema and router definitions.
130-148: AppIcon component is clean and type-safe.The discriminated union pattern enables proper type narrowing, and the component correctly handles both icon formats. The implementation is straightforward and easy to maintain.
242-264: JetBrains submenu implementation is well-structured.The submenu cleanly groups all JetBrains IDEs, preventing menu clutter. The implementation correctly uses the
@superset/uidropdown sub-menu components and maintains consistency with the main menu items (including keyboard shortcut display when applicable).
Replace react-icons monochrome icons with official JetBrains color SVG logos from https://github.com/JetBrains/logos repository. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the JetBrains logo with text to the icon-only version for better appearance in the dropdown menu. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (2)
73-76: getAppOption fallback is slightly brittle to APP_OPTIONS reorderingUsing
ALL_APP_OPTIONSfor lookup correctly supports both built‑in and JetBrains apps. The fallbackAPP_OPTIONS[1](cursor) works today but couples behavior to the array index.Consider making the fallback explicit by id to avoid accidental changes if
APP_OPTIONSis reordered:-const ALL_APP_OPTIONS = [...APP_OPTIONS, ...JETBRAINS_OPTIONS]; - -const getAppOption = (id: ExternalApp) => - ALL_APP_OPTIONS.find((app) => app.id === id) ?? APP_OPTIONS[1]; +const ALL_APP_OPTIONS = [...APP_OPTIONS, ...JETBRAINS_OPTIONS]; + +const DEFAULT_APP_ID: ExternalApp = "cursor"; + +const getAppOption = (id: ExternalApp) => + ALL_APP_OPTIONS.find((app) => app.id === id) ?? + ALL_APP_OPTIONS.find((app) => app.id === DEFAULT_APP_ID)!;
178-208: JetBrains submenu integrates correctly; consider DRYing item renderingThe
DropdownMenuSubfor JetBrains looks correctly wired: trigger label and icon are clear, andJETBRAINS_OPTIONSmap to items with the same structure and shortcut hint behavior as the main list. Functionally this is solid.There is some duplication between the main
APP_OPTIONS.mapblock and theJETBRAINS_OPTIONS.mapblock (same item layout and shortcut logic). If it starts to grow further, you could introduce a small non‑component helper to render an item to reduce repetition while still honoring the “one component per file” guideline.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (13)
apps/desktop/src/renderer/assets/app-icons/appcode.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/clion.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/datagrip.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/fleet.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/goland.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/intellij.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/jetbrains.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/phpstorm.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/pycharm.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/rider.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/rubymine.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/rustrover.svgis excluded by!**/*.svgapps/desktop/src/renderer/assets/app-icons/webstorm.svgis excluded by!**/*.svg
📒 Files selected for processing (1)
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/{components,pages}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
**/{components,pages}/**/*.tsx: Use one folder per component with structureComponentName/ComponentName.tsxplusindex.tsfor barrel export
Create one component per file - do not use multi-component files
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Avoidanytype in TypeScript unless absolutely necessary
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/src/{renderer,shared,preload}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in renderer process code or shared code in the desktop app
Files:
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (2)
apps/desktop/src/main/lib/db/schemas.ts (1)
ExternalApp(96-96)packages/ui/src/components/dropdown-menu.tsx (4)
DropdownMenuSub(257-257)DropdownMenuSubTrigger(258-258)DropdownMenuSubContent(259-259)DropdownMenuItem(251-251)
⏰ 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/components/OpenInButton/OpenInButton.tsx (3)
3-12: Correct use of dropdown submenu primitivesImporting
DropdownMenuSub,DropdownMenuSubContent, andDropdownMenuSubTriggerfrom the shared UI layer cleanly aligns the new JetBrains submenu with existing dropdown patterns; no issues here.As per coding guidelines, this keeps renderer code using shared UI components without pulling in Node APIs.
18-38: JetBrains icon imports look consistent with existing asset usageThe new JetBrains icon imports follow the existing
renderer/assets/app-icons/*pattern and keep all icons as static resources in the renderer, which is consistent with current usage and respects the “no Node modules in renderer” rule.As per coding guidelines, using
renderer/*aliases here is appropriate.
58-71: JETBRAINS_OPTIONS mapping is straightforward and type‑safe
JETBRAINS_OPTIONScleanly maps each JetBrainsExternalAppid to a label and icon, mirroring the existingAPP_OPTIONSstructure. Assuming the ids are present inEXTERNAL_APPS, this should remain type‑safe and future‑proof.
Summary
Changes
apps/desktop/src/main/lib/db/schemas.ts- Added 12 JetBrains IDE types toEXTERNAL_APPSapps/desktop/src/lib/trpc/routers/external/index.ts- Added macOS open commands for all JetBrains IDEsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx- Added JetBrains submenu with icons from react-iconsTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.