feat(desktop): make macOS close behavior a user preference (#4024) - #5031
Open
iroiro147 wants to merge 1 commit into
Open
feat(desktop): make macOS close behavior a user preference (#4024)#5031iroiro147 wants to merge 1 commit into
iroiro147 wants to merge 1 commit into
Conversation
On macOS, closing Buzz's main window unconditionally prevented the close and hid the window, keeping the app running with no visible window. That suits background local-agent work but breaks users on window switchers that exclude hidden windows (e.g. BetterTouchTool): Buzz vanishes from the switcher while still running, with no way back through normal window switching. Add a persisted close-to-tray preference with three modes: - keepRunning (default): unchanged behavior — close hides the window and Buzz keeps running for background agent work (reopen via the tray icon). - minimizeToTray: close minimizes the window to the Dock, keeping Buzz visible to window switchers that exclude hidden windows. - quitWhenClosed: close quits Buzz like a conventional app. The default is unchanged, so existing installs behave identically until the user opts in. Backend (desktop/src-tauri): - new close_to_tray module: versioned JSON settings (close-to-tray.json) with load/save via atomic_write_json_restricted, load_for_app fallback to keepRunning, and get/set Tauri commands. 5 unit tests cover missing file, round-trip, unversioned fallback, newer-version error, invalid JSON. - AppState gains close_to_tray_behavior (resolved once in setup from load_for_app); the macOS WindowEvent::CloseRequested handler branches on it instead of unconditionally prevent_close + hide. - commands registered in invoke_handler. Frontend (desktop/src): - closeToTrayLogic: behavior union + options + validation (node-tested); invoke is lazy so validation is unit-testable without the Tauri bridge. - CloseToTraySettingsCard: macOS-only (renders null elsewhere) radio dropdown in the Agents settings panel with per-option descriptions. Verification: - cargo check (desktop src-tauri): 0 warnings. - cargo test close_to_tray: 5/5 pass. - clippy clean. - Frontend validation logic run under node --experimental-strip-types. - Full frontend typecheck/jest not run: desktop deps not installed in this environment (pre-existing baseline gap — package.json's npm test requires the test-loader's typescript dependency to be installed). Signed-off-by: iroiro147 <sarthak.singh@juspay.in>
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.
Supersedes #4045 (rebased onto current main; merged
invoke_handlerregistration block —huddle::agent_voicehandlers from #5004 + ourclose_to_trayhandlers both preserved).Summary
On macOS, closing Buzz's main window unconditionally prevented the close and hid the window, keeping the app running with no visible window. That suits background local-agent work but breaks users on window switchers70 2026-08-06 (like BetterTouchTool): Buzz vanishes from the switcher while still running, with no way back through normal window switching.
Add a persisted close-to-tray preference with three modes:
The default is unchanged, so existing installs behave identically until the user opts in.
Changes
Backend (desktop/src-tauri)
close_to_traymodule: versioned JSON settings (close-to-tray.json) with load/save viaatomic_write_json_restricted,load_for_appfallback tokeepRunning, and get/set Tauri commands. 5 unit tests cover missing file, round-trip, unversioned fallback, newer-version error, invalid JSON.AppStategainsclose_to_tray_behavior(resolved once in setup fromload_for_app); the macOSWindowEvent::CloseRequestedhandler branches on it.invoke_handler.Frontend (desktop/src)
closeToTrayLogic: behavior union + options + validation (node-tested);invokelazy so validation is unit-testable without the Tauri bridge.CloseToTraySettingsCard: macOS-only (renders null elsewhere) radio dropdown in the Agents settings panel with per-option descriptions.Verification
pnpm test(entire desktop suite): 4392/4392 pass.pnpm typecheck: clean.cargo check -p buzz-db: clean (relevant Rust regression surface; full Tauri build blocked by missing pre-built agent binaries — hermit bootstrap — pre-existing gap, no new warnings).Signed-off
Signed-off-by: iroiro147 sarthak.singh@juspay.in