tauri_plugin_notification/
lib.rs

1// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5//! Send message notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
6
7#![doc(
8    html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
9    html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
10)]
11
12use serde::Serialize;
13#[cfg(mobile)]
14use tauri::plugin::PluginHandle;
15#[cfg(desktop)]
16use tauri::AppHandle;
17use tauri::{
18    plugin::{Builder, TauriPlugin},
19    Manager, Runtime,
20};
21
22pub use models::*;
23pub use tauri::plugin::PermissionState;
24
25#[cfg(desktop)]
26mod desktop;
27#[cfg(mobile)]
28mod mobile;
29
30mod commands;
31mod error;
32mod models;
33
34pub use error::{Error, Result};
35
36#[cfg(desktop)]
37pub use desktop::Notification;
38#[cfg(mobile)]
39pub use mobile::Notification;
40
41/// The notification builder.
42#[derive(Debug)]
43pub struct NotificationBuilder<R: Runtime> {
44    #[cfg(desktop)]
45    app: AppHandle<R>,
46    #[cfg(mobile)]
47    handle: PluginHandle<R>,
48    pub(crate) data: NotificationData,
49}
50
51impl<R: Runtime> NotificationBuilder<R> {
52    #[cfg(desktop)]
53    fn new(app: AppHandle<R>) -> Self {
54        Self {
55            app,
56            data: Default::default(),
57        }
58    }
59
60    #[cfg(mobile)]
61    fn new(handle: PluginHandle<R>) -> Self {
62        Self {
63            handle,
64            data: Default::default(),
65        }
66    }
67
68    /// Sets the notification identifier.
69    pub fn id(mut self, id: i32) -> Self {
70        self.data.id = id;
71        self
72    }
73
74    /// Identifier of the {@link Channel} that deliveres this notification.
75    ///
76    /// If the channel does not exist, the notification won't fire.
77    /// Make sure the channel exists with {@link listChannels} and {@link createChannel}.
78    pub fn channel_id(mut self, id: impl Into<String>) -> Self {
79        self.data.channel_id.replace(id.into());
80        self
81    }
82
83    /// Sets the notification title.
84    pub fn title(mut self, title: impl Into<String>) -> Self {
85        self.data.title.replace(title.into());
86        self
87    }
88
89    /// Sets the notification body.
90    pub fn body(mut self, body: impl Into<String>) -> Self {
91        self.data.body.replace(body.into());
92        self
93    }
94
95    /// Schedule this notification to fire on a later time or a fixed interval.
96    pub fn schedule(mut self, schedule: Schedule) -> Self {
97        self.data.schedule.replace(schedule);
98        self
99    }
100
101    /// Multiline text.
102    /// Changes the notification style to big text.
103    /// Cannot be used with `inboxLines`.
104    pub fn large_body(mut self, large_body: impl Into<String>) -> Self {
105        self.data.large_body.replace(large_body.into());
106        self
107    }
108
109    /// Detail text for the notification with `largeBody`, `inboxLines` or `groupSummary`.
110    pub fn summary(mut self, summary: impl Into<String>) -> Self {
111        self.data.summary.replace(summary.into());
112        self
113    }
114
115    /// Defines an action type for this notification.
116    pub fn action_type_id(mut self, action_type_id: impl Into<String>) -> Self {
117        self.data.action_type_id.replace(action_type_id.into());
118        self
119    }
120
121    /// Identifier used to group multiple notifications.
122    ///
123    /// <https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier>
124    pub fn group(mut self, group: impl Into<String>) -> Self {
125        self.data.group.replace(group.into());
126        self
127    }
128
129    /// Instructs the system that this notification is the summary of a group on Android.
130    pub fn group_summary(mut self) -> Self {
131        self.data.group_summary = true;
132        self
133    }
134
135    /// The sound resource name for the notification.
136    pub fn sound(mut self, sound: impl Into<String>) -> Self {
137        self.data.sound.replace(sound.into());
138        self
139    }
140
141    /// Append an inbox line to the notification.
142    /// Changes the notification style to inbox.
143    /// Cannot be used with `largeBody`.
144    ///
145    /// Only supports up to 5 lines.
146    pub fn inbox_line(mut self, line: impl Into<String>) -> Self {
147        self.data.inbox_lines.push(line.into());
148        self
149    }
150
151    /// Notification icon.
152    ///
153    /// On Android the icon must be placed in the app's `res/drawable` folder.
154    pub fn icon(mut self, icon: impl Into<String>) -> Self {
155        self.data.icon.replace(icon.into());
156        self
157    }
158
159    /// Notification large icon (Android).
160    ///
161    /// The icon must be placed in the app's `res/drawable` folder.
162    pub fn large_icon(mut self, large_icon: impl Into<String>) -> Self {
163        self.data.large_icon.replace(large_icon.into());
164        self
165    }
166
167    /// Icon color on Android.
168    pub fn icon_color(mut self, icon_color: impl Into<String>) -> Self {
169        self.data.icon_color.replace(icon_color.into());
170        self
171    }
172
173    /// Append an attachment to the notification.
174    pub fn attachment(mut self, attachment: Attachment) -> Self {
175        self.data.attachments.push(attachment);
176        self
177    }
178
179    /// Adds an extra payload to store in the notification.
180    pub fn extra(mut self, key: impl Into<String>, value: impl Serialize) -> Self {
181        self.data
182            .extra
183            .insert(key.into(), serde_json::to_value(value).unwrap());
184        self
185    }
186
187    /// If true, the notification cannot be dismissed by the user on Android.
188    ///
189    /// An application service must manage the dismissal of the notification.
190    /// It is typically used to indicate a background task that is pending (e.g. a file download)
191    /// or the user is engaged with (e.g. playing music).
192    pub fn ongoing(mut self) -> Self {
193        self.data.ongoing = true;
194        self
195    }
196
197    /// Automatically cancel the notification when the user clicks on it.
198    pub fn auto_cancel(mut self) -> Self {
199        self.data.auto_cancel = true;
200        self
201    }
202
203    /// Changes the notification presentation to be silent on iOS (no badge, no sound, not listed).
204    pub fn silent(mut self) -> Self {
205        self.data.silent = true;
206        self
207    }
208}
209
210/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the notification APIs.
211pub trait NotificationExt<R: Runtime> {
212    fn notification(&self) -> &Notification<R>;
213}
214
215impl<R: Runtime, T: Manager<R>> crate::NotificationExt<R> for T {
216    fn notification(&self) -> &Notification<R> {
217        self.state::<Notification<R>>().inner()
218    }
219}
220
221/// Initializes the plugin.
222pub fn init<R: Runtime>() -> TauriPlugin<R> {
223    Builder::new("notification")
224        .invoke_handler(tauri::generate_handler![
225            commands::notify,
226            commands::request_permission,
227            commands::is_permission_granted
228        ])
229        .js_init_script(include_str!("init-iife.js").replace(
230            "__TEMPLATE_windows__",
231            if cfg!(windows) { "true" } else { "false" },
232        ))
233        .setup(|app, api| {
234            #[cfg(mobile)]
235            let notification = mobile::init(app, api)?;
236            #[cfg(desktop)]
237            let notification = desktop::init(app, api)?;
238            app.manage(notification);
239            Ok(())
240        })
241        .build()
242}