entracte_lib/notifications.rs
1use tauri::plugin::PermissionState;
2use tauri::{AppHandle, Runtime};
3
4/// Whether the app must call `request_permission()` for the current
5/// notification permission state before any `.show()` will surface a
6/// banner.
7///
8/// On macOS a fresh install starts in `Prompt` / `PromptWithRationale`
9/// (the OS "not determined" authorization status). Until the app
10/// explicitly requests authorization, `tauri-plugin-notification`'s
11/// `.show()` posts into a notification centre the app was never
12/// registered with, so every banner is silently dropped — which is why
13/// the pre-break notification never appeared even though the scheduler
14/// fired it (#135). `permission_state()` reporting a determined value
15/// (`Granted` / `Denied`) means the user has already answered, so we
16/// neither need nor want to re-prompt.
17pub fn should_request_notification_permission(state: PermissionState) -> bool {
18 matches!(
19 state,
20 PermissionState::Prompt | PermissionState::PromptWithRationale
21 )
22}
23
24/// Ensure the OS notification authorization has been requested at least
25/// once so scheduled break / pre-break / screen-time banners actually
26/// surface. Queries the current permission, and only on an undetermined
27/// state does it raise the request (which shows the macOS authorization
28/// dialog and registers the app with the notification centre).
29///
30/// The pure undetermined-vs-determined decision lives in
31/// [`should_request_notification_permission`]; everything here is the
32/// plugin-FFI shim around it.
33pub fn ensure_permission_requested<R: Runtime>(app: &AppHandle<R>) {
34 use tauri_plugin_notification::NotificationExt;
35
36 let state = match app.notification().permission_state() {
37 Ok(state) => state,
38 Err(e) => {
39 log::warn!("notifications: could not read permission state: {e}");
40 return;
41 }
42 };
43 if !should_request_notification_permission(state) {
44 return;
45 }
46 match app.notification().request_permission() {
47 Ok(new_state) => {
48 log::info!("notifications: requested permission, now {new_state:?}");
49 }
50 Err(e) => {
51 log::warn!("notifications: permission request failed: {e}");
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn requests_when_undetermined() {
62 assert!(should_request_notification_permission(
63 PermissionState::Prompt
64 ));
65 assert!(should_request_notification_permission(
66 PermissionState::PromptWithRationale
67 ));
68 }
69
70 #[test]
71 fn does_not_request_when_already_decided() {
72 assert!(!should_request_notification_permission(
73 PermissionState::Granted
74 ));
75 assert!(!should_request_notification_permission(
76 PermissionState::Denied
77 ));
78 }
79}