feat(settings): add "Close to tray" option#2845
Open
BlueManCZ wants to merge 1 commit intogitify-app:mainfrom
Open
feat(settings): add "Close to tray" option#2845BlueManCZ wants to merge 1 commit intogitify-app:mainfrom
BlueManCZ wants to merge 1 commit intogitify-app:mainfrom
Conversation
Adds an opt-in System setting (default off) that hides the menubar
window on a WM-initiated close request instead of quitting the app.
Useful on Linux tiling WMs where a global "close window" shortcut
otherwise terminates Gitify.
The implementation works around two quirks documented inline in
src/main/lifecycle/window.ts:
1. menubar's own `close` listener nulls `mb.window` regardless of
preventDefault, and listeners run in registration order, so we
capture the BrowserWindow at config time and restore the reference
after hiding so the next tray click reuses the same window
(preserving renderer state).
2. On Wayland, `hide()` is deferred via setImmediate to let the close
cancellation unwind — a synchronous hide can leave the surface
mapped but without keyboard input routing.
A `window-all-closed` handler acts as a safety net: if the WM tears
down the window despite preventDefault (a known Wayland edge case,
electron/electron#34788, #35657), it suppresses the default quit so
the tray icon stays put and menubar can recreate the window.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in "Close to tray" checkbox to System settings (default off). When enabled, pressing your window manager's close shortcut (e.g.
Super+Qon Hyprland,Alt+F4on Windows,Cmd+Won macOS) hides the Gitify popup instead of quitting the app — the same way Slack, Signal, and most messaging apps behave.Why
On Linux tiling WMs (Hyprland, i3, Sway, …) users typically bind a global "close window" shortcut. Today, hitting that shortcut on Gitify's popup terminates the entire app — you lose the tray icon and have to re-launch Gitify to get notifications back. Pressing
Escor clicking outside already hides the popup gracefully; this PR makes the WM close shortcut do the same when the user opts in.The setting is off by default, so existing behavior is preserved. Real ways to quit Gitify (tray right-click → "Quit Gitify",
Ctrl/Cmd+Q) are unchanged and always work regardless of the setting.Where it lives
Settings → System → Close to tray(right after "Open at startup"), with a tooltip explaining the behavior and how to actually quit.Behavior matrix
EscCtrl/Cmd+QImplementation notes for reviewers
The two non-obvious bits are documented inline in
src/main/lifecycle/window.ts. Calling them out here so the diff doesn't look surprising:Capturing the
BrowserWindowreference at config time.menubarregisters its owncloselistener (windowClear) when the window is created. It nullsmb.windowregardless ofpreventDefault, and listeners run in registration order — so readingmb.windowinside our handler returnsundefined. We capture the reference at the top ofconfigureWindowEventsand, after hiding, restore menubar's internal field so the next tray click reuses the same window (keeping renderer state — keyboard listeners, notification cache, scroll, etc.). The private-field write is wrapped in atry/catchso a future menubar refactor degrades to "fresh window per show" rather than throwing.Deferring
hide()viasetImmediate. On Wayland, callinghide()synchronously afterpreventDefaulton a frameless surface can leave the window mapped but without keyboard input routing. Deferring lets the close cancellation unwind first.window-all-closedsafety net. Suppresses the default Electron quit so the tray icon stays put if the WM tears the window down despitepreventDefault— a known Wayland edge case ([Bug]: On Wayland closing apps to the system tray, then reopening them makes the app forget which monitor it was previously opened on (Signal, ProtonVPN, MullvadVPN) electron/electron#34788, #35657).menubarthen recreates the window on the next tray click.Test plan
main.Ctrl/Cmd+Qaccelerator fully exits regardless of the setting.Escstill hides the popup regardless of the setting.pnpm testpasses (11 tests forlifecycle/window.ts, Settings snapshot updated, no other test changes needed).🤖 Generated with Claude Code