tauri_plugin_notifications/
desktop.rs1use serde::de::DeserializeOwned;
6use tauri::{
7 plugin::{PermissionState, PluginApi},
8 AppHandle, Runtime,
9};
10
11use crate::NotificationsBuilder;
12
13pub fn init<R: Runtime, C: DeserializeOwned>(
14 app: &AppHandle<R>,
15 _api: PluginApi<R, C>,
16) -> crate::Result<Notifications<R>> {
17 Ok(Notifications(app.clone()))
18}
19
20pub struct Notifications<R: Runtime>(AppHandle<R>);
24
25impl<R: Runtime> crate::NotificationsBuilder<R> {
26 pub fn show(self) -> crate::Result<()> {
27 let mut notification = imp::Notification::new(self.app.config().identifier.clone());
28
29 if let Some(title) = self
30 .data
31 .title
32 .or_else(|| self.app.config().product_name.clone())
33 {
34 notification = notification.title(title);
35 }
36 if let Some(body) = self.data.body {
37 notification = notification.body(body);
38 }
39 if let Some(icon) = self.data.icon {
40 notification = notification.icon(icon);
41 }
42
43 notification.show()?;
44
45 Ok(())
46 }
47}
48
49impl<R: Runtime> Notifications<R> {
50 pub fn builder(&self) -> NotificationsBuilder<R> {
51 NotificationsBuilder::new(self.0.clone())
52 }
53
54 pub fn request_permission(&self) -> crate::Result<PermissionState> {
55 Ok(PermissionState::Granted)
56 }
57
58 pub fn register_for_push_notifications(&self) -> crate::Result<String> {
59 Err(crate::Error::Io(std::io::Error::other(
60 "Push notifications are not supported on desktop platforms",
61 )))
62 }
63
64 pub fn permission_state(&self) -> crate::Result<PermissionState> {
65 Ok(PermissionState::Granted)
66 }
67}
68
69mod imp {
70 #[cfg(windows)]
73 use std::path::MAIN_SEPARATOR as SEP;
74
75 #[allow(dead_code)]
99 #[derive(Debug, Default)]
100 pub struct Notification {
101 body: Option<String>,
103 title: Option<String>,
105 icon: Option<String>,
107 identifier: String,
109 }
110
111 impl Notification {
112 pub fn new(identifier: impl Into<String>) -> Self {
114 Self {
115 identifier: identifier.into(),
116 ..Default::default()
117 }
118 }
119
120 #[must_use]
122 pub fn body(mut self, body: impl Into<String>) -> Self {
123 self.body = Some(body.into());
124 self
125 }
126
127 #[must_use]
129 pub fn title(mut self, title: impl Into<String>) -> Self {
130 self.title = Some(title.into());
131 self
132 }
133
134 #[must_use]
136 pub fn icon(mut self, icon: impl Into<String>) -> Self {
137 self.icon = Some(icon.into());
138 self
139 }
140
141 pub fn show(self) -> crate::Result<()> {
163 let mut notification = notify_rust::Notification::new();
164 if let Some(body) = self.body {
165 notification.body(&body);
166 }
167 if let Some(title) = self.title {
168 notification.summary(&title);
169 }
170 if let Some(icon) = self.icon {
171 notification.icon(&icon);
172 } else {
173 notification.auto_icon();
174 }
175 #[cfg(windows)]
176 {
177 let exe = tauri::utils::platform::current_exe()?;
178 let exe_dir = exe.parent().expect("failed to get exe directory");
179 let curr_dir = exe_dir.display().to_string();
180 if !(curr_dir.ends_with(format!("{SEP}target{SEP}debug").as_str())
182 || curr_dir.ends_with(format!("{SEP}target{SEP}release").as_str()))
183 {
184 notification.app_id(&self.identifier);
185 }
186 }
187 #[cfg(target_os = "macos")]
188 {
189 let _ = notify_rust::set_application(if tauri::is_dev() {
190 "com.apple.Terminal"
191 } else {
192 &self.identifier
193 });
194 }
195
196 tauri::async_runtime::spawn(async move {
197 let _ = notification.show();
198 });
199
200 Ok(())
201 }
202 }
203}