fix: keep notifications alive so clicks still work on macOS
GC was collecting the JS Notification object after ~1 min, silently
killing click handlers. Hold a ref in a Set, release on click/close/
failed. Also order app.focus({steal}) before restore/show so the app
comes forward when minimized to Dock or Cmd+H'd.
This commit is contained in:
@@ -581,12 +581,23 @@ const focusForegroundWindow = () => {
|
||||
const target = state.mainWindow && !state.mainWindow.isDestroyed()
|
||||
? state.mainWindow
|
||||
: windows.find((window) => window.isVisible()) || windows[0];
|
||||
if (target.isMinimized()) target.restore();
|
||||
if (!target.isVisible()) target.show();
|
||||
target.focus();
|
||||
// macOS: bring the app to foreground FIRST. When the window is minimized
|
||||
// to the Dock or hidden via Cmd+H, the app is in the background, and
|
||||
// subsequent window.show/restore/focus calls won't pull it forward
|
||||
// unless app.focus runs first.
|
||||
if (process.platform === 'darwin') app.focus({ steal: true });
|
||||
if (target.isMinimized()) target.restore();
|
||||
target.show();
|
||||
target.focus();
|
||||
if (typeof target.moveTop === 'function') target.moveTop();
|
||||
};
|
||||
|
||||
// Keep references to live notifications so they aren't garbage-collected
|
||||
// before the OS fires click/close. On macOS, losing the JS reference causes
|
||||
// click events to silently stop firing after ~1 min.
|
||||
// See https://blog.bloomca.me/2025/02/22/electron-mac-notifications
|
||||
const activeNotifications = new Set();
|
||||
|
||||
const maybeShowNativeNotification = (rawInput) => {
|
||||
const payload = normalizeNotificationInput(rawInput);
|
||||
const requireHidden = Boolean(payload.requireHidden ?? payload.require_hidden);
|
||||
@@ -614,12 +625,18 @@ const maybeShowNativeNotification = (rawInput) => {
|
||||
...(process.platform === 'darwin' ? { sound: 'Glass' } : {}),
|
||||
});
|
||||
|
||||
activeNotifications.add(notification);
|
||||
const release = () => { activeNotifications.delete(notification); };
|
||||
|
||||
notification.on('click', () => {
|
||||
focusForegroundWindow();
|
||||
if (sessionId) {
|
||||
emitToAllWindows('openchamber:open-session', { sessionId });
|
||||
}
|
||||
release();
|
||||
});
|
||||
notification.on('close', release);
|
||||
notification.on('failed', release);
|
||||
|
||||
notification.show();
|
||||
};
|
||||
@@ -2179,9 +2196,8 @@ app.on('activate', async () => {
|
||||
if (windows.length > 0) {
|
||||
const visibleWindow = windows.find((window) => window.isVisible());
|
||||
const targetWindow = visibleWindow || state.mainWindow || windows[0];
|
||||
if (!targetWindow.isVisible()) {
|
||||
targetWindow.show();
|
||||
}
|
||||
if (targetWindow.isMinimized()) targetWindow.restore();
|
||||
targetWindow.show();
|
||||
targetWindow.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user