Skip to main content

leptos_use_web_notification/
options.rs

1use default_struct_builder::DefaultBuilder;
2use std::rc::Rc;
3use wasm_bindgen::JsValue;
4
5#[derive(Default, Clone, Copy, Eq, PartialEq, Debug)]
6pub enum NotificationDirection {
7    #[default]
8    Auto,
9    LeftToRight,
10    RightToLeft,
11}
12
13impl From<NotificationDirection> for web_sys::NotificationDirection {
14    fn from(direction: NotificationDirection) -> Self {
15        match direction {
16            NotificationDirection::Auto => Self::Auto,
17            NotificationDirection::LeftToRight => Self::Ltr,
18            NotificationDirection::RightToLeft => Self::Rtl,
19        }
20    }
21}
22
23/// Options for [`use_web_notification_with_options`](crate::use_web_notification_with_options).
24/// See [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/notification) for more info.
25///
26/// The following implementations are missing:
27#[derive(DefaultBuilder, Clone)]
28#[cfg_attr(feature = "ssr", allow(dead_code))]
29pub struct UseWebNotificationOptions {
30    /// The title property of the Notification interface indicates
31    /// the title of the notification
32    #[builder(into)]
33    pub(crate) title: String,
34
35    /// The body string of the notification as specified in the constructor's
36    /// options parameter.
37    #[builder(into)]
38    body: Option<String>,
39
40    /// The text direction of the notification as specified in the constructor's
41    /// options parameter. Can be `LeftToRight`, `RightToLeft` or `Auto` (default).
42    /// See [`web_sys::NotificationDirection`] for more info.
43    direction: NotificationDirection,
44
45    /// The language code of the notification as specified in the constructor's
46    /// options parameter.
47    #[builder(into)]
48    language: Option<String>,
49
50    /// The ID of the notification(if any) as specified in the constructor's options
51    /// parameter.
52    #[builder(into)]
53    tag: Option<String>,
54
55    /// The URL of the image used as an icon of the notification as specified
56    /// in the constructor's options parameter.
57    #[builder(into)]
58    icon: Option<String>,
59
60    /// The URL of the image to be displayed as part of the notification as specified
61    /// in the constructor's options parameter.
62    #[builder(into)]
63    image: Option<String>,
64
65    /// A boolean value indicating that a notification should remain active until the
66    /// user clicks or dismisses it, rather than closing automatically.
67    require_interaction: bool,
68
69    /// A boolean value specifying whether the user should be notified after a new notification replaces an old one.
70    /// The default is `false`, which means they won't be notified. If `true`, then `tag` also must be set.
71    #[builder(into)]
72    renotify: bool,
73
74    /// A boolean value specifying whether the notification should be silent, regardless of the device settings.
75    /// The default is `null`, which means the notification is not silent. If `true`, then the notification will be silent.
76    #[builder(into)]
77    silent: Option<bool>,
78
79    /// A `Vec<u16>` specifying the vibration pattern in milliseconds for vibrating and not vibrating.
80    /// The last entry can be a vibration since it stops automatically after each period.
81    #[builder(into)]
82    vibrate: Option<Vec<u16>>,
83
84    /// Called when the user clicks on displayed `Notification`.
85    pub(crate) on_click: Rc<dyn Fn(web_sys::Event)>,
86
87    /// Called when the user closes a `Notification`.
88    pub(crate) on_close: Rc<dyn Fn(web_sys::Event)>,
89
90    /// Called when something goes wrong with a `Notification`
91    /// (in many cases an error preventing the notification from being displayed.)
92    pub(crate) on_error: Rc<dyn Fn(web_sys::Event)>,
93
94    /// Called when a `Notification` is displayed
95    pub(crate) on_show: Rc<dyn Fn(web_sys::Event)>,
96}
97
98impl Default for UseWebNotificationOptions {
99    fn default() -> Self {
100        Self {
101            title: "".to_string(),
102            body: None,
103            direction: NotificationDirection::default(),
104            language: None,
105            tag: None,
106            icon: None,
107            image: None,
108            require_interaction: false,
109            renotify: false,
110            silent: None,
111            vibrate: None,
112            on_click: Rc::new(|_| {}),
113            on_close: Rc::new(|_| {}),
114            on_error: Rc::new(|_| {}),
115            on_show: Rc::new(|_| {}),
116        }
117    }
118}
119
120impl From<&UseWebNotificationOptions> for web_sys::NotificationOptions {
121    fn from(options: &UseWebNotificationOptions) -> Self {
122        let web_sys_options = Self::new();
123
124        web_sys_options.set_dir(options.direction.into());
125        web_sys_options.set_require_interaction(options.require_interaction);
126        web_sys_options.set_renotify(options.renotify);
127        web_sys_options.set_silent(options.silent);
128
129        if let Some(body) = &options.body {
130            web_sys_options.set_body(body);
131        }
132
133        if let Some(icon) = &options.icon {
134            web_sys_options.set_icon(icon);
135        }
136
137        if let Some(image) = &options.image {
138            web_sys_options.set_image(image);
139        }
140
141        if let Some(language) = &options.language {
142            web_sys_options.set_lang(language);
143        }
144
145        if let Some(tag) = &options.tag {
146            web_sys_options.set_tag(tag);
147        }
148
149        if let Some(vibrate) = &options.vibrate {
150            web_sys_options.set_vibrate(&vibration_pattern_to_jsvalue(vibrate));
151        }
152        web_sys_options
153    }
154}
155
156/// Options for [`UseWebNotificationReturn::show`](crate::UseWebNotificationReturn::show).
157///
158/// This can be used to override options passed to [`use_web_notification`](crate::use_web_notification).
159/// See [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/notification) for more info.
160///
161/// The following implementations are missing:
162#[derive(DefaultBuilder, Default)]
163#[cfg_attr(feature = "ssr", allow(dead_code))]
164pub struct ShowOptions {
165    /// The title property of the Notification interface indicates
166    /// the title of the notification
167    #[builder(into)]
168    pub(crate) title: Option<String>,
169
170    /// The body string of the notification as specified in the constructor's
171    /// options parameter.
172    #[builder(into)]
173    body: Option<String>,
174
175    /// The text direction of the notification as specified in the constructor's
176    /// options parameter. Can be `LeftToRight`, `RightToLeft` or `Auto` (default).
177    /// See [`web_sys::NotificationDirection`] for more info.
178    #[builder(into)]
179    direction: Option<NotificationDirection>,
180
181    /// The language code of the notification as specified in the constructor's
182    /// options parameter.
183    #[builder(into)]
184    language: Option<String>,
185
186    /// The ID of the notification(if any) as specified in the constructor's options
187    /// parameter.
188    #[builder(into)]
189    tag: Option<String>,
190
191    /// The URL of the image used as an icon of the notification as specified
192    /// in the constructor's options parameter.
193    #[builder(into)]
194    icon: Option<String>,
195
196    /// The URL of the image to be displayed as part of the notification as specified
197    /// in the constructor's options parameter.
198    #[builder(into)]
199    image: Option<String>,
200
201    /// A boolean value indicating that a notification should remain active until the
202    /// user clicks or dismisses it, rather than closing automatically.
203    #[builder(into)]
204    require_interaction: Option<bool>,
205
206    /// A boolean value specifying whether the user should be notified after a new notification replaces an old one.
207    /// The default is `false`, which means they won't be notified. If `true`, then `tag` also must be set.
208    #[builder(into)]
209    renotify: Option<bool>,
210
211    /// A boolean value specifying whether the notification should be silent, regardless of the device settings.
212    /// The default is `null`, which means the notification is not silent. If `true`, then the notification will be silent.
213    #[builder(into)]
214    silent: Option<bool>,
215
216    /// A `Vec<u16>` specifying the vibration pattern in milliseconds for vibrating and not vibrating.
217    /// The last entry can be a vibration since it stops automatically after each period.
218    #[builder(into)]
219    vibrate: Option<Vec<u16>>,
220}
221
222#[cfg(not(feature = "ssr"))]
223impl ShowOptions {
224    pub(crate) fn override_notification_options(&self, options: &mut web_sys::NotificationOptions) {
225        if let Some(direction) = self.direction {
226            options.set_dir(direction.into());
227        }
228
229        if let Some(require_interaction) = self.require_interaction {
230            options.set_require_interaction(require_interaction);
231        }
232
233        if let Some(body) = &self.body {
234            options.set_body(body);
235        }
236
237        if let Some(icon) = &self.icon {
238            options.set_icon(icon);
239        }
240
241        if let Some(image) = &self.image {
242            options.set_image(image);
243        }
244
245        if let Some(language) = &self.language {
246            options.set_lang(language);
247        }
248
249        if let Some(tag) = &self.tag {
250            options.set_tag(tag);
251        }
252
253        if let Some(renotify) = self.renotify {
254            options.set_renotify(renotify);
255        }
256
257        if let Some(silent) = self.silent {
258            options.set_silent(Some(silent));
259        }
260
261        if let Some(vibrate) = &self.vibrate {
262            options.set_vibrate(&vibration_pattern_to_jsvalue(vibrate));
263        }
264    }
265}
266
267/// Helper function to convert a slice of `u16` into a `JsValue` array that represents a vibration pattern
268fn vibration_pattern_to_jsvalue(pattern: &[u16]) -> JsValue {
269    let array = js_sys::Array::new();
270    for &value in pattern.iter() {
271        array.push(&JsValue::from(value));
272    }
273    array.into()
274}