fix(notifications): restore macOS banners + Debug dropdown to verify - #32
Merged
Conversation
Adds a "Debug Notifications" dropdown next to the existing "Debug Updater" in the About section. The dropdown exposes every OS notification type Meetily emits (recording started/stopped/paused/ resumed, transcription complete, meeting reminder, system error, generic test) and fires each one through the real production code path so developers and support engineers can validate the notification channel end-to-end without starting a real meeting. Backend (Rust): - New serde-tagged DebugNotificationKind enum (snake_case) and a single debug_show_notification(kind) Tauri command that dispatches to the existing internal helpers in notifications/commands.rs. - New show_meeting_reminder_notification helper matching the shape of show_recording_paused_notification (no helper previously existed for the meeting reminder flow; the method lived only on NotificationManager). - Command registered in the notification commands group of lib.rs. Frontend (React): - About.tsx adds a DropdownMenu styled to match the adjacent Debug Updater button (variant=ghost, size=sm, text-xs ml-2) with Bell and ChevronDown affordances. - A DEBUG_NOTIFICATION_ITEMS table maps each kind to a label and to the notification_preferences flag on the Rust side. The handler pre-reads is_notification_system_ready and get_notification_settings before invoking, so it can surface a toast.info explaining otherwise-silent suppression when consent is off or the per-type preference is disabled. Production suppression behaviour is unchanged. Docs: - NOTIFICATION_TESTING.md points at the new UI dropdown as the primary per-type test path; the dev-console invoke recipes remain for auto-consent / bypass scenarios. Brainstorm: docs/brainstorms/2026-04-18-notification-debug-dropdown-brainstorm.md
…ionCenter tauri-plugin-notification -> notify-rust -> mac-notification-sys uses the deprecated NSUserNotification API whose banner delivery is broken on modern macOS. Notifications land in Notification Center but no banner ever appears top-right. Route macOS notifications through UNUserNotificationCenter directly (via objc2-user- notifications). Install a UNUserNotificationCenterDelegate whose willPresent handler returns .banner|.list|.sound so foreground-app notifications show banners. Keep the existing tauri-plugin-notification path for Windows and Linux. First launch of the new build will re-prompt for notification permission (NS and UN grants live in separate slots). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add Phase 2 section to the macOS notifications solution doc covering the NSUserNotification→UNUserNotificationCenter migration: new symptoms, root cause, the UNUserNotificationCenterDelegate willPresent handler, first-launch re-prompt behavior, and the Critical-Alerts-entitlement gotcha (map Critical→TimeSensitive). Rewrite NOTIFICATION_TESTING.md troubleshooting around UN authorization state, Alert Style verification, Focus/Scheduled-Summary/Deliver-Quietly pitfalls, and the killall usernoted kick. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AzimovS
added a commit
that referenced
this pull request
Apr 20, 2026
… docs) - Cfg-gate the `tauri-plugin-notification` fallback blocks in show_recording_started_notification and show_recording_stopped_notification to #[cfg(not(target_os = "macos"))]. On macOS those paths would route through the deprecated NSUserNotification API (which doesn't deliver banners) and could race with our UNUserNotificationCenterDelegate via last-writer-wins setDelegate:. On macOS, if the manager fails to initialize, log a warn and drop the notification rather than silently deliver via the broken path. - Add per-unsafe-block SAFETY comments throughout macos_un.rs: the define_class! attributes (super = NSObject, NSObjectProtocol, UNUserNotificationCenterDelegate, method selector), the msg_send![super, init] in BannerDelegate::new, and the error_message helper (including a /// # Safety doc). Closes todos/001, todos/002 from the review of PR #32. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
AzimovS
added a commit
that referenced
this pull request
Apr 20, 2026
… docs) (#33) - Cfg-gate the `tauri-plugin-notification` fallback blocks in show_recording_started_notification and show_recording_stopped_notification to #[cfg(not(target_os = "macos"))]. On macOS those paths would route through the deprecated NSUserNotification API (which doesn't deliver banners) and could race with our UNUserNotificationCenterDelegate via last-writer-wins setDelegate:. On macOS, if the manager fails to initialize, log a warn and drop the notification rather than silently deliver via the broken path. - Add per-unsafe-block SAFETY comments throughout macos_un.rs: the define_class! attributes (super = NSObject, NSObjectProtocol, UNUserNotificationCenterDelegate, method selector), the msg_send![super, init] in BannerDelegate::new, and the error_message helper (including a /// # Safety doc). Closes todos/001, todos/002 from the review of PR #32.
4 tasks
AzimovS
added a commit
that referenced
this pull request
Apr 21, 2026
`UNUserNotificationCenter` dereferences `NSBundle.mainBundle` and throws `NSInternalInconsistencyException: bundleProxyForCurrentProcess is nil` when the executable is launched directly (e.g. `pnpm run tauri dev`, which runs `target/debug/meetily` rather than the bundled `.app`). Since commits #32/#33 migrated macOS notifications from the legacy `NSUserNotification` path to UN, every `tauri dev` run crashes at startup. Skip the UN calls when `current_exe()` has no `.app` ancestor. `request_authorization` returns `Err` (not `Ok(false)`) so `manager.rs` falls into its existing `Err` arm and does not persist `system_permission_granted = false` — the dev run and the bundled `.app` share `~/Library/Application Support/com.meetily.ai/`, so persisting `false` would silently suppress every real notification until the user re-granted consent. `show()` returns `Ok(())`; callers do not store state on success. Bundled `.app` behavior is unchanged.
AzimovS
added a commit
that referenced
this pull request
Apr 24, 2026
Prepares a release containing the work merged since v0.1.15: - feat(detection): mic-activity meeting auto-detection on macOS (#35) - feat(transcription): retry with backoff + in-transcript failure placeholder (#39) - feat(summary): TownHall template (#30), current template name in dropdown (#31), specificity prompt tweak (#37) - feat(remote): test-connection button + model selection surface improvements (#28, #29) - fix(notifications): migrate to UNUserNotificationCenter (#32), SAFETY + fallback race fixes (#33), unbundled-dev crash guard (#38), drop OS recording banners and flip auto_save default to false (#36) - chore(about): drop Zackriya services CTA (#40) Behavior change to call out in release notes: fresh installs (and users with no stored recording_preferences.json) now default auto_save to false — audio files are not written to disk unless the user opts in via Recording Settings. Existing users with saved preferences are unaffected. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two changes that are best shipped together because the first proves the second is real:
NotificationType.The macOS bug
tauri-plugin-notification→notify-rust→mac-notification-sysuses[NSUserNotificationCenter deliverNotification:].NSUserNotificationwas deprecated in macOS 10.14 (2018) and its banner path has been broken on modern macOS for years. On macOS 26, every API contract returns success but no banner ever fires. Upstream fix is stalled: mac-notification-sys PR #51 (draft since Nov 2025), tauri plugins-workspace RFC #2134 (no PR).What changed
SystemNotificationHandler::show_notificationdispatches to a newmacos_unmodule that usesUNUserNotificationCenterdirectly viaobjc2-user-notifications. AUNUserNotificationCenterDelegatewhosewillPresentreturns.banner|.list|.soundis installed once (retained inOnceCell) so foreground-app notifications produce banners — the real fix.tauri-plugin-notificationis unchanged.requestAuthorizationWithOptions— which means first launch of this build re-prompts for notification permission. NS and UN grants live in separate slots.NotificationPriority::Criticalmaps toUNNotificationInterruptionLevel::TimeSensitive, notCritical. Real Critical requires Apple's Critical Alerts entitlement we don't have.Deps added (macOS-only):
objc2,objc2-foundation,objc2-user-notifications,block2.Testing
Manually verified on macOS 26.4.1 from an ad-hoc-signed debug bundle. All 8
DebugNotificationKindvariants produce visible top-right banners within ~1s, each with the Meetily icon and an entry in Notification Center.Installed UNUserNotificationCenterDelegate (willPresent → Banner|List|Sound)once,UN present: id=... title=... level=...per sendcargo checkclean (same preexisting warnings, no new ones)Docs updated
docs/solutions/build-errors/macos-dev-build-notifications-and-signing.md: new Phase 2: NS → UN migration section covering root cause, solution, re-prompt behavior, and gotchas specific to the new path (cb753b9)frontend/src-tauri/NOTIFICATION_TESTING.md: reworked troubleshooting around UN authorization state, Alert Style, Focus / Scheduled Summary / Deliver Quietly, and thekillall usernotedkick (cb753b9)Caveats for reviewers
tauri devstill can't deliver banners —UNUserNotificationCenterrequires a validCFBundleIdentifier, whichtauri devdoesn't provide. Test from a built bundle (see solution doc).addNotificationRequestfails, we surface the error to the caller (same contract as before) rather than silently trying the broken NS path. Logs include the underlyingNSErrorlocalized description.Post-Deploy Monitoring & Validation
This is a local desktop app with no production backend — no dashboards, no log queries. Validation is user-driven.
await window.__TAURI_INTERNALS__.invoke('get_notification_stats')in DevTools —system_permission_grantedmust betrue. If not, follow the re-prompt procedure inNOTIFICATION_TESTING.md.cfg.frontend/src-tauri/src/notifications/system.rs.🤖 Generated with Claude Code