pytauri_core/plugins/notification/
mod.rs1use std::{
2 error::Error,
3 fmt::{Debug, Display, Formatter},
4};
5
6use pyo3::{prelude::*, types::PyDict};
7use pyo3_utils::{
8 from_py_dict::{derive_from_py_dict, FromPyDict as _, NotRequired},
9 py_wrapper::{PyWrapper, PyWrapperT2},
10};
11use tauri_plugin_notification::{self as plugin, NotificationExt as _};
12
13use crate::{
14 ext_mod::{manager_method_impl, ImplManager},
15 tauri_runtime::Runtime,
16};
17
18#[derive(Debug)]
19struct PluginError(plugin::Error);
20
21impl Display for PluginError {
22 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23 Display::fmt(&self.0, f)
24 }
25}
26
27impl Error for PluginError {}
28
29impl From<PluginError> for PyErr {
30 fn from(value: PluginError) -> Self {
31 match value.0 {
32 plugin::Error::Io(e) => e.into(),
33 }
34 }
35}
36
37impl From<plugin::Error> for PluginError {
38 fn from(value: plugin::Error) -> Self {
39 Self(value)
40 }
41}
42
43#[non_exhaustive]
45pub struct NotificationBuilderArgs {
46 id: NotRequired<i32>,
47 channel_id: NotRequired<String>,
48 title: NotRequired<String>,
49 body: NotRequired<String>,
50 large_body: NotRequired<String>,
52 summary: NotRequired<String>,
53 action_type_id: NotRequired<String>,
54 group: NotRequired<String>,
55 group_summary: bool,
56 sound: NotRequired<String>,
57 inbox_line: NotRequired<String>,
58 icon: NotRequired<String>,
59 large_icon: NotRequired<String>,
60 icon_color: NotRequired<String>,
61 ongoing: bool,
64 auto_cancel: bool,
65 silent: bool,
66}
67
68derive_from_py_dict!(NotificationBuilderArgs {
69 #[default]
70 id,
71 #[default]
72 channel_id,
73 #[default]
74 title,
75 #[default]
76 body,
77 #[default]
78 large_body,
79 #[default]
80 summary,
81 #[default]
82 action_type_id,
83 #[default]
84 group,
85 #[default]
86 group_summary,
87 #[default]
88 sound,
89 #[default]
90 inbox_line,
91 #[default]
92 icon,
93 #[default]
94 large_icon,
95 #[default]
96 icon_color,
97 #[default]
98 ongoing,
99 #[default]
100 auto_cancel,
101 #[default]
102 silent,
103});
104
105impl NotificationBuilderArgs {
106 fn from_kwargs(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<Option<Self>> {
109 kwargs
110 .map(NotificationBuilderArgs::from_py_dict)
111 .transpose()
112 }
113
114 fn apply_to_builder(
115 self,
116 mut builder: plugin::NotificationBuilder<Runtime>,
117 ) -> plugin::NotificationBuilder<Runtime> {
118 let Self {
119 id,
120 channel_id,
121 title,
122 body,
123 large_body,
124 summary,
125 action_type_id,
126 group,
127 group_summary,
128 sound,
129 inbox_line,
130 icon,
131 large_icon,
132 icon_color,
133 ongoing,
134 auto_cancel,
135 silent,
136 } = self;
137
138 if let Some(id) = id.0 {
139 builder = builder.id(id);
140 }
141 if let Some(channel_id) = channel_id.0 {
142 builder = builder.channel_id(channel_id);
143 }
144 if let Some(title) = title.0 {
145 builder = builder.title(title);
146 }
147 if let Some(body) = body.0 {
148 builder = builder.body(body);
149 }
150 if let Some(large_body) = large_body.0 {
151 builder = builder.large_body(large_body);
152 }
153 if let Some(summary) = summary.0 {
154 builder = builder.summary(summary);
155 }
156 if let Some(action_type_id) = action_type_id.0 {
157 builder = builder.action_type_id(action_type_id);
158 }
159 if let Some(group) = group.0 {
160 builder = builder.group(group);
161 }
162 if group_summary {
163 builder = builder.group_summary();
164 }
165 if let Some(sound) = sound.0 {
166 builder = builder.sound(sound);
167 }
168 if let Some(inbox_line) = inbox_line.0 {
169 builder = builder.inbox_line(inbox_line);
170 }
171 if let Some(icon) = icon.0 {
172 builder = builder.icon(icon);
173 }
174 if let Some(large_icon) = large_icon.0 {
175 builder = builder.large_icon(large_icon);
176 }
177 if let Some(icon_color) = icon_color.0 {
178 builder = builder.icon_color(icon_color);
179 }
180 if ongoing {
181 builder = builder.ongoing();
182 }
183 if auto_cancel {
184 builder = builder.auto_cancel();
185 }
186 if silent {
187 builder = builder.silent();
188 }
189
190 builder
191 }
192}
193
194#[pyclass(frozen)]
196#[non_exhaustive]
197pub struct NotificationBuilder(pub PyWrapper<PyWrapperT2<plugin::NotificationBuilder<Runtime>>>);
198
199impl NotificationBuilder {
200 fn new(builder: plugin::NotificationBuilder<Runtime>) -> Self {
201 Self(PyWrapper::new2(builder))
202 }
203}
204
205#[pymethods]
206impl NotificationBuilder {
207 #[pyo3(signature = (**kwargs))]
208 fn show(&self, kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<()> {
209 let args = NotificationBuilderArgs::from_kwargs(kwargs)?;
210
211 let mut builder = self.0.try_take_inner()??;
212
213 if let Some(args) = args {
214 builder = args.apply_to_builder(builder);
215 }
216
217 builder
219 .show()
220 .map_err(PluginError::from)
221 .map_err(PyErr::from)
222 }
223}
224
225#[pyclass(frozen)]
227#[non_exhaustive]
228pub struct NotificationExt;
229
230pub type ImplNotificationExt = ImplManager;
232
233#[pymethods]
234impl NotificationExt {
235 #[staticmethod]
236 fn builder(slf: ImplNotificationExt, py: Python<'_>) -> PyResult<NotificationBuilder> {
237 manager_method_impl!(py, &slf, |_py, manager| {
238 let builder = manager.notification().builder();
240 Ok(NotificationBuilder::new(builder))
241 })?
242 }
243}
244
245#[pymodule(submodule, gil_used = false)]
247pub mod notification {
248 #[pymodule_export]
249 pub use super::{NotificationBuilder, NotificationExt};
250
251 pub use super::{ImplNotificationExt, NotificationBuilderArgs};
252}