Make notifications appear on screen, and be clickable

Three separate faults, all mine:

set_application was never called, so mac-notification-sys looked up an
app named "use_default", failed, and posted every notification as
com.apple.Finder - wearing Finder's alert style rather than this app's.

NSUserNotificationCenter suppresses the banner whenever the posting app
is frontmost unless the delegate implements shouldPresentNotification:.
The crate's delegate implements only delivery and activation, so the
method is added to its class at runtime. Without it, Gmail notifying
while you sit in Odoo - same window, still frontmost - is never seen,
which is the case the whole design exists for.

send_notification only waits for a response when the options ask it to.
Passing None returned instantly with NotificationResponse::None, so the
click branch was unreachable. Waiting parks a thread and a notification
left unread never resolves, so waiters are capped at 32.

The diagnostic now records the raise before blocking, since with
wait_for_click a notification sitting on screen otherwise read as
"none yet".
This commit is contained in:
2026-09-01 13:25:02 +02:00
parent 3525d454bf
commit 21a9f065f0
3 changed files with 129 additions and 6 deletions
@@ -184,6 +184,24 @@ click handler, which is the only thing that knows which message the notification
about. This is why notifications are raised through `mac-notification-sys` rather than
Tauri's notification plugin: the plugin cannot report a click.
Three things had to be right for a banner to actually appear on screen, and each was
wrong at first:
1. **Identity.** `set_application` has to be called with the bundle identifier. Left alone,
mac-notification-sys looks up an application named `"use_default"`, fails, and posts as
`com.apple.Finder` — so notifications arrive wearing another app's alert style.
2. **Presentation while frontmost.** `NSUserNotificationCenter` suppresses the banner
whenever the posting app is in front, delivering it silently to Notification Centre
instead, unless the delegate implements `shouldPresentNotification:`. The crate's
delegate implements only delivery and activation, so the missing method is added to its
class at runtime. Without it, Gmail notifying while you sit in Odoo — the same window,
still frontmost — would never be seen.
3. **Waiting for the click.** `send_notification` only blocks for a response when the
options ask it to. Passing `None` returns immediately with `NotificationResponse::None`,
so no click is ever observed. Waiting costs a parked thread, and a notification left in
Notification Centre never resolves, so the number of waiters is capped at 32; past that
the notification still appears but cannot be clicked through.
Service-worker push is **not** covered — only notifications a page raises while it is open.
## Zoom