diff --git a/electron/ipc/system.ts b/electron/ipc/system.ts index 8e07e39..cc701a4 100644 --- a/electron/ipc/system.ts +++ b/electron/ipc/system.ts @@ -332,12 +332,15 @@ export function setupSystemHandlers(): void { const title = typeof payload?.title === 'string' ? payload.title.trim() : ''; const body = typeof payload?.body === 'string' ? payload.body : ''; const mainWindow = getMainWindow(); + const suppressSystemNotification = mainWindow?.isVisible() === true + && !mainWindow.isMinimized() + && mainWindow.isMaximized(); if (!title) { return false; } - if (Notification.isSupported()) { + if (!suppressSystemNotification && Notification.isSupported()) { try { const notification = new Notification({ title, diff --git a/toju-app/src/app/domains/notifications/README.md b/toju-app/src/app/domains/notifications/README.md index 14c7592..0a7b6d1 100644 --- a/toju-app/src/app/domains/notifications/README.md +++ b/toju-app/src/app/domains/notifications/README.md @@ -203,6 +203,7 @@ Additional runtime guards: The Electron main process handles the actual desktop notification and window-attention behavior. - `show-desktop-notification` creates a system `Notification` with the window icon when supported. +- `show-desktop-notification` skips the OS toast while the main window is visible and maximized. - Notification clicks restore, show, and focus the main window. - `request-window-attention` flashes the taskbar entry directly when Electron is minimized or otherwise backgrounded and actionable unread exists. - `show-desktop-notification` can still request attention for live toast delivery. @@ -210,7 +211,7 @@ The Electron main process handles the actual desktop notification and window-att ### Platform-specific policy -- Windows: the facade also plays `AppSound.Notification` before showing the desktop notification. +- Windows: the facade only plays `AppSound.Notification` when the app is not the active selected window. - Linux: desktop alerts are expected to surface through the system notification center, with window attention requested when the app is backgrounded. - macOS and browser-only builds use the same desktop notification adapter, but there is no extra renderer-side sound policy in this domain. diff --git a/toju-app/src/app/domains/notifications/application/notifications.facade.ts b/toju-app/src/app/domains/notifications/application/notifications.facade.ts index e74e8a2..46a8968 100644 --- a/toju-app/src/app/domains/notifications/application/notifications.facade.ts +++ b/toju-app/src/app/domains/notifications/application/notifications.facade.ts @@ -206,7 +206,7 @@ export class NotificationsFacade { !context.isWindowFocused || !context.isDocumentVisible ); - if (this.platformKind === 'windows') { + if (this.shouldPlayNotificationSound()) { this.audio.play(AppSound.Notification); } @@ -349,6 +349,14 @@ export class NotificationsFacade { }; } + private shouldPlayNotificationSound(): boolean { + return this.platformKind === 'windows' && !this.isWindowActive(); + } + + private isWindowActive(): boolean { + return this._windowFocused() && this._documentVisible() && !this._windowMinimized(); + } + private ensureRoomTracking(roomId: string, channelId: string, baselineTimestamp: number): void { const settings = this._settings(); diff --git a/toju-app/src/app/domains/notifications/feature/settings/notifications-settings.component.html b/toju-app/src/app/domains/notifications/feature/settings/notifications-settings.component.html index a849232..faa360e 100644 --- a/toju-app/src/app/domains/notifications/feature/settings/notifications-settings.component.html +++ b/toju-app/src/app/domains/notifications/feature/settings/notifications-settings.component.html @@ -11,8 +11,8 @@

Delivery

- Desktop alerts use the system notification center on Linux and request taskbar attention when the app is not focused. Windows also plays the - configured notification sound. + Desktop alerts use the system notification center on Linux and request taskbar attention when the app is not focused. Maximized app window + suppress system popups, and only play the configured notification sound while the app is in the background.