fix: use setActivationPolicy for proper Dock behavior#113
Conversation
Replace app.dock.hide()/show() with app.setActivationPolicy(): - Normal mode: 'regular' (dock icon + running dot + App Switcher) - Menu bar mode: 'accessory' (no dock icon, same as LSUIElement) setActivationPolicy is the official macOS API for this, cleaner than dock.hide() which has known Electron bugs. LSUIElement=true kept in Info.plist to prevent dock icon flash on app launch. Caveat: switching to 'accessory' hides all windows — re-show with 100ms delay after policy change. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughVersion 1.0.71 release updates macOS dock behavior to use app activation policy instead of hide/show methods, and adds a tray context menu item to toggle between Normal and Menu Bar application modes. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Tray as Tray Menu
participant Main as Main Process
participant IPC as IPC Channel
participant App as Electron App
User->>Tray: Click mode toggle item
Tray->>Main: Call onToggleAppMode()
Main->>Main: Compute opposite mode
Main->>IPC: Emit 'set-app-mode' event
IPC->>App: Handle set-app-mode
alt Mode = 'menubar'
App->>App: setActivationPolicy('accessory')
App->>App: Hide all windows
App->>App: Wait 100ms
App->>App: Re-show switcher window
else Mode = 'normal'
App->>App: setActivationPolicy('regular')
end
App-->>User: App mode updated
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Shows 'Switch to Menu Bar Mode' or 'Switch to Normal App Mode' at the top of the tray context menu. Reuses the same IPC logic as the Settings toggle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@cubic-dev-ai review |
|
🧠 Learnings used✅ Actions performedReview triggered.
|
@grimmerk I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/main.ts (1)
1983-1991: Add a guard for destroyed window in the setTimeout callback.The
winreference is captured before the 100ms delay, but the window could be destroyed during that time (e.g., user quits the app). While unlikely in practice, adding a defensive check would prevent potential errors.🛡️ Suggested fix
app.setActivationPolicy('accessory'); // accessory mode hides all windows — re-show after short delay const win = getSwitcherWindow(); if (win) { - setTimeout(() => { win.show(); win.focus(); }, 100); + setTimeout(() => { + if (win && !win.isDestroyed()) { + win.show(); + win.focus(); + } + }, 100); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main.ts` around lines 1983 - 1991, The delayed callback captures the BrowserWindow reference `win` but doesn't check if it was destroyed during the 100ms delay; update the setTimeout callback that currently calls `win.show()` and `win.focus()` to first verify the window still exists and is not destroyed (e.g., check `win` is truthy and `!win.isDestroyed()` or equivalent) before calling show/focus; apply this guard in the code path where `getSwitcherWindow()` is used so the callback safely no-ops if the window was closed.
🤖 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/main.ts`:
- Around line 1983-1991: The delayed callback captures the BrowserWindow
reference `win` but doesn't check if it was destroyed during the 100ms delay;
update the setTimeout callback that currently calls `win.show()` and
`win.focus()` to first verify the window still exists and is not destroyed
(e.g., check `win` is truthy and `!win.isDestroyed()` or equivalent) before
calling show/focus; apply this guard in the code path where
`getSwitcherWindow()` is used so the callback safely no-ops if the window was
closed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d1d03344-8f53-4146-96f0-3e502b7b3776
📒 Files selected for processing (4)
CHANGELOG.mdpackage.jsonsrc/TrayGenerator.tssrc/main.ts
Summary
Replace
app.dock.hide()/show()withapp.setActivationPolicy()for proper Dock behavior in Normal App mode.Before (app.dock.hide/show)
dock.hide()only removes dot, icon may persist if manually pinneddock.hide()(breaksapp.hide(), conflicts withsetVisibleOnAllWorkspaces)After (setActivationPolicy)
'regular'— proper Dock icon with running dot, App Switcher visible'accessory'— no Dock icon at all (same as LSUIElement)LSUIElement=truekept in Info.plist to prevent Dock icon flash on app launchCaveat
'accessory'hides all windows — re-shown with 100ms delaysetActivationPolicyis a standard macOS API (NSApplicationActivationPolicy), not a hackTray menu mode toggle
Test plan
🤖 On behalf of @grimmerk — generated with Claude Code
Summary by CodeRabbit
Bug Fixes
New Features