fix: add context menu to root window for deep link launch flow#3271
fix: add context menu to root window for deep link launch flow#3271jeanfbrito merged 2 commits intodevfrom
Conversation
The right-click context menu was only attached to server webview webContents, not to the root window's own webContents. This meant the "Enter your server URL" screen (rendered in the root window) had no context menu, preventing users from pasting via right-click when the app was launched through a deep link.
WalkthroughAdded a custom edit-focused context menu to the root window and registered a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/ui/main/rootWindow.ts (1)
584-588: Thecontext-menulistener registration is called only once during app initialization, so multiple listener accumulation is not a practical concern.
showRootWindow()is invoked a single time at startup (src/main.ts:104), and the context-menu listener at lines 584–588 is registered once per application lifecycle. The singleton pattern used for_rootWindowensures the listener is not duplicated.Additionally,
event.preventDefault()on thecontext-menuevent is unnecessary—the event is informational in Electron and has no default behavior to prevent. It can be safely removed.If you prefer to add defensive guard logic or move listener registration elsewhere for consistency, that would be an optional improvement. The current code functions correctly as-is.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/main/rootWindow.ts` around lines 584 - 588, The context-menu handler registered via browserWindow.webContents.on('context-menu', ...) calls event.preventDefault(), which is unnecessary for Electron's informational 'context-menu' event; remove the event.preventDefault() call and leave the listener registration as-is (it is only created once when showRootWindow() initializes the singleton _rootWindow). Ensure createRootWindowContextMenu(params) is still invoked and menu.popup({ window: browserWindow }) remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/ui/main/rootWindow.ts`:
- Around line 584-588: The context-menu handler registered via
browserWindow.webContents.on('context-menu', ...) calls event.preventDefault(),
which is unnecessary for Electron's informational 'context-menu' event; remove
the event.preventDefault() call and leave the listener registration as-is (it is
only created once when showRootWindow() initializes the singleton _rootWindow).
Ensure createRootWindowContextMenu(params) is still invoked and menu.popup({
window: browserWindow }) remains unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f2625569-6668-4646-8dcd-a065d644072b
📒 Files selected for processing (1)
src/ui/main/rootWindow.ts
📜 Review details
⏰ 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). (4)
- GitHub Check: build (windows-latest, windows)
- GitHub Check: build (ubuntu-latest, linux)
- GitHub Check: check (ubuntu-latest)
- GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from@rocket.chat/fuselagefor all UI work and only create custom components when Fuselage doesn't provide what's needed
CheckTheme.d.tsfor valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux
Files:
src/ui/main/rootWindow.ts
🔇 Additional comments (2)
src/ui/main/rootWindow.ts (2)
3-16: LGTM!The import additions are well-organized, correctly separating type-only imports (
ContextMenuParams) from runtime imports (Menu). Both are required for the new context menu functionality.
528-579: LGTM!Well-structured implementation with:
- Defensive defaults in destructuring preventing runtime errors if
editFlagsproperties are missing- Proper i18n integration for translated labels (all keys exist in i18n files)
- Correct platform-specific redo accelerator handling (Windows uses Ctrl+Y by convention)
Windows installer download |
macOS installer download |
Linux installer download |
The update-available handler unconditionally honored skippedUpdateVersion, silently suppressing skipped versions even when the user manually triggered Check for Updates from the About dialog. This left no recovery path for users who skipped a version and later changed their mind. Add an isUserInitiatedCheck flag so the skip preference only applies to automatic startup checks, not user-initiated ones.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/updates/main.ts (1)
349-366: The try/catch cannot catch errors fromcheckForUpdates()inside setTimeout.The
checkForUpdates()call is asynchronous within the setTimeout callback, so any thrown error or rejected promise won't be caught by the outer try/catch. While theautoUpdater.addListener('error', ...)at lines 321-330 handles update errors, the try/catch here is misleading.Additionally, the purpose of the 100ms delay is unclear—consider adding a comment explaining why it's needed.
♻️ Suggested refactor: Move error handling inside setTimeout or remove misleading try/catch
listen(UPDATES_CHECK_FOR_UPDATES_REQUESTED, async () => { - try { - isUserInitiatedCheck = true; - setTimeout(() => { + isUserInitiatedCheck = true; + // Delay check to allow UI state to settle (e.g., dialog animation) + setTimeout(async () => { + try { autoUpdater.checkForUpdates(); - }, 100); - } catch (error) { - error instanceof Error && - dispatch({ - type: UPDATES_ERROR_THROWN, - payload: { - message: error.message, - stack: error.stack, - name: error.name, - }, - }); - } + } catch (error) { + error instanceof Error && + dispatch({ + type: UPDATES_ERROR_THROWN, + payload: { + message: error.message, + stack: error.stack, + name: error.name, + }, + }); + } + }, 100); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/updates/main.ts` around lines 349 - 366, The try/catch around the listen(UPDATES_CHECK_FOR_UPDATES_REQUESTED, ...) handler cannot catch errors thrown inside the setTimeout callback; move error handling into that callback (or remove the outer try/catch) so failures from autoUpdater.checkForUpdates are caught and dispatched: inside the setTimeout wrap autoUpdater.checkForUpdates in a try/catch or call autoUpdater.checkForUpdates().catch(...) and dispatch UPDATES_ERROR_THROWN with error.message/name/stack (use the same payload shape currently used); also add a short comment explaining why the 100ms delay exists (or remove the delay if unnecessary) and keep isUserInitiatedCheck assignment and existing autoUpdater.addListener('error', ...) intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/updates/main.ts`:
- Around line 349-366: The try/catch around the
listen(UPDATES_CHECK_FOR_UPDATES_REQUESTED, ...) handler cannot catch errors
thrown inside the setTimeout callback; move error handling into that callback
(or remove the outer try/catch) so failures from autoUpdater.checkForUpdates are
caught and dispatched: inside the setTimeout wrap autoUpdater.checkForUpdates in
a try/catch or call autoUpdater.checkForUpdates().catch(...) and dispatch
UPDATES_ERROR_THROWN with error.message/name/stack (use the same payload shape
currently used); also add a short comment explaining why the 100ms delay exists
(or remove the delay if unnecessary) and keep isUserInitiatedCheck assignment
and existing autoUpdater.addListener('error', ...) intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 639f26fd-db66-488a-ab81-19b71f7da6a9
📒 Files selected for processing (1)
src/updates/main.ts
📜 Review details
⏰ 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). (3)
- GitHub Check: check (ubuntu-latest)
- GitHub Check: check (macos-latest)
- GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from@rocket.chat/fuselagefor all UI work and only create custom components when Fuselage doesn't provide what's needed
CheckTheme.d.tsfor valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux
Files:
src/updates/main.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: Ram-sah19
Repo: RocketChat/Rocket.Chat.Electron PR: 3254
File: .github/workflows/build-release.yml:80-94
Timestamp: 2026-03-11T06:38:40.426Z
Learning: In the RocketChat/Rocket.Chat.Electron repository, the issues flagged in `.github/workflows/build-release.yml` (e.g., `node12` runtime in the release action and missing `snapcraft_token` input), i18n files, and `electron-builder.json` are pre-existing in the `develop` branch and are pulled in during merge conflict resolution. Do not flag these as new issues introduced by PRs that only modify `src/injected.ts` and `src/ui/main/rootWindow.ts`.
🔇 Additional comments (3)
src/updates/main.ts (3)
165-166: LGTM, but consider resetting the flag after check completion.The module-level flag correctly differentiates user-initiated vs automatic checks. While current code paths set it appropriately before each
checkForUpdates()call, consider resettingisUserInitiatedCheck = falsein theupdate-availableandupdate-not-availablehandlers to prevent accidental misuse if future code adds additional check triggers.
249-252: LGTM - Logic correctly bypasses skip filter for user-initiated checks.The condition properly allows users who manually click "Check for Updates" to re-discover a previously skipped version, while automatic startup checks continue to respect the skip preference.
332-346: LGTM - Startup check correctly marked as automatic.The flag is appropriately set to
falsebefore the awaited check, and errors are properly caught.
Summary
Fixes the right-click context menu being unresponsive on the "Enter your server URL" screen when the app is launched via a deep link.
https://rocketchat.atlassian.net/browse/CORE-1600
context-menuevent listener on the root window'swebContentswith standard edit actions (Undo, Redo, Cut, Copy, Paste, Select All)Test plan
rocketchat://URL)Summary by CodeRabbit
New Features
Bug Fixes