diff --git a/docs/notifications.md b/docs/notifications.md index c862dc443..d33965dc8 100644 --- a/docs/notifications.md +++ b/docs/notifications.md @@ -9,8 +9,21 @@ notifications; unset or any other value keeps normal behavior. This development gate never rewrites saved preferences. Settings shows the pause and how to remove it; normal behavior still honors account choices and system permission. Production builds ignore this variable. -Browser sound uses the Notification API. Desktop sound is managed in OS settings; -there is no separate audio player. +Notification sound is app-owned on browser and desktop: Buzz bundles a set of +alert sounds under `public/sounds/`, and the notifications service plays the +per-category selection (with a shared default) in the running app after a +banner submission is accepted. OS banners are always submitted silent, so the +system never plays a second sound: the browser banner sets `silent: true`, the +Windows toast is built with silent audio (`sound(None)`), Linux Notify sends +the standard `suppress-sound` hint, and the macOS backend never sets a sound +name. Because a submission can resolve after state has moved on, the audio +decision stays under revalidation until the platform resolves it: any interval +of Sound turned off, alerts or the category disabled, or revoked +access/eligibility cancels the sound for good (without affecting the banner), +and the sound also requires the same live account generation and currently +allowed, eligible, Sound-enabled state when the submission is accepted. +Settings offers per-category sound selection with an in-app preview; the +Sound switch turns playback off without disabling alerts. ```ts export const inject = ["notifications"]; @@ -89,7 +102,8 @@ mac-notification-sys on macOS, the freedesktop notification interface through zbus on Linux, and tauri-winrt-notification on Windows. Linux uses the already locked zbus dependency directly because notify-rust's send-then-listen wrapper can lose early actions. No dependency upgrade or new native FFI is needed. -Banner permission and sound remain system-controlled; no permission-only plugin +Banner permission remains system-controlled; alert sound is app-owned and plays +in the renderer, not through the native backends. No permission-only plugin or synthetic desktop notification is installed. The macOS Dock settings below provide an explicit system authorization action. The main-window-only bridge carries display text and an opaque presentation ID, never an account, credential @@ -112,8 +126,10 @@ focus policy still applies. Dismissal never navigates. Observable send/focus failures reach Settings without retry; a focus error does not discard navigation. Banner permission state is not observable through these backends. Settings -describes permission and sound as system-controlled, without ineffective desktop -banner permission or sound controls. The bridge accepts a submission before waiting for +omits ineffective desktop banner permission controls (the page subtitle uses the +reference copy and does not describe permission handling); sound controls are +effective on desktop because +playback happens in the app. The bridge accepts a submission before waiting for interaction: acceptance is **not** proof that a visible banner appeared. The macOS backend does not expose all delivery failures, and no uniform withdrawal/receipt guarantee is promised. diff --git a/public/sounds/bong.mp3 b/public/sounds/bong.mp3 new file mode 100644 index 000000000..a62f2a442 Binary files /dev/null and b/public/sounds/bong.mp3 differ diff --git a/public/sounds/bong.svg b/public/sounds/bong.svg new file mode 100644 index 000000000..908808729 --- /dev/null +++ b/public/sounds/bong.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/boo.mp3 b/public/sounds/boo.mp3 new file mode 100644 index 000000000..1d672a7d9 Binary files /dev/null and b/public/sounds/boo.mp3 differ diff --git a/public/sounds/boo.svg b/public/sounds/boo.svg new file mode 100644 index 000000000..977037bd3 --- /dev/null +++ b/public/sounds/boo.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/dng.mp3 b/public/sounds/dng.mp3 new file mode 100644 index 000000000..29b111b10 Binary files /dev/null and b/public/sounds/dng.mp3 differ diff --git a/public/sounds/dng.svg b/public/sounds/dng.svg new file mode 100644 index 000000000..b702b0534 --- /dev/null +++ b/public/sounds/dng.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/doo.mp3 b/public/sounds/doo.mp3 new file mode 100644 index 000000000..6eb8f3b56 Binary files /dev/null and b/public/sounds/doo.mp3 differ diff --git a/public/sounds/doo.svg b/public/sounds/doo.svg new file mode 100644 index 000000000..5fe260a23 --- /dev/null +++ b/public/sounds/doo.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/doodone.mp3 b/public/sounds/doodone.mp3 new file mode 100644 index 000000000..c21ee7ad0 Binary files /dev/null and b/public/sounds/doodone.mp3 differ diff --git a/public/sounds/doodone.svg b/public/sounds/doodone.svg new file mode 100644 index 000000000..bc6275de4 --- /dev/null +++ b/public/sounds/doodone.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/doong.mp3 b/public/sounds/doong.mp3 new file mode 100644 index 000000000..7c81649b9 Binary files /dev/null and b/public/sounds/doong.mp3 differ diff --git a/public/sounds/doong.svg b/public/sounds/doong.svg new file mode 100644 index 000000000..43728d02b --- /dev/null +++ b/public/sounds/doong.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/doop.mp3 b/public/sounds/doop.mp3 new file mode 100644 index 000000000..bbece1cb7 Binary files /dev/null and b/public/sounds/doop.mp3 differ diff --git a/public/sounds/doop.svg b/public/sounds/doop.svg new file mode 100644 index 000000000..4fdce28a3 --- /dev/null +++ b/public/sounds/doop.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/flirl.mp3 b/public/sounds/flirl.mp3 new file mode 100644 index 000000000..1edaa772e Binary files /dev/null and b/public/sounds/flirl.mp3 differ diff --git a/public/sounds/flirl.svg b/public/sounds/flirl.svg new file mode 100644 index 000000000..5daa5e2a4 --- /dev/null +++ b/public/sounds/flirl.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/flutter.mp3 b/public/sounds/flutter.mp3 new file mode 100644 index 000000000..f6b7e3db6 Binary files /dev/null and b/public/sounds/flutter.mp3 differ diff --git a/public/sounds/flutter.svg b/public/sounds/flutter.svg new file mode 100644 index 000000000..81a87769c --- /dev/null +++ b/public/sounds/flutter.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/oh-no.mp3 b/public/sounds/oh-no.mp3 new file mode 100644 index 000000000..c95b6dfb5 Binary files /dev/null and b/public/sounds/oh-no.mp3 differ diff --git a/public/sounds/oh-no.svg b/public/sounds/oh-no.svg new file mode 100644 index 000000000..26ad14a5b --- /dev/null +++ b/public/sounds/oh-no.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/ping.mp3 b/public/sounds/ping.mp3 new file mode 100644 index 000000000..9cb4dc635 Binary files /dev/null and b/public/sounds/ping.mp3 differ diff --git a/public/sounds/ping.svg b/public/sounds/ping.svg new file mode 100644 index 000000000..c96cfbdea --- /dev/null +++ b/public/sounds/ping.svg @@ -0,0 +1 @@ + diff --git a/public/sounds/unison.mp3 b/public/sounds/unison.mp3 new file mode 100644 index 000000000..143119017 Binary files /dev/null and b/public/sounds/unison.mp3 differ diff --git a/public/sounds/unison.svg b/public/sounds/unison.svg new file mode 100644 index 000000000..6759d3df7 --- /dev/null +++ b/public/sounds/unison.svg @@ -0,0 +1 @@ + diff --git a/src-tauri/src/notifications.rs b/src-tauri/src/notifications.rs index e0973fbc8..466b44d14 100644 --- a/src-tauri/src/notifications.rs +++ b/src-tauri/src/notifications.rs @@ -230,6 +230,11 @@ fn show( }) .title(&title) .text1(&body) + // Sound is app-owned: the renderer plays the selected bundled + // sound after delivery. Without this the toast defaults to the + // native notification sound (`sound(None)` emits + // `