1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Send toast notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
//! 
//! The APIs must be added to tauri.allowlist.notification in tauri.conf.json:
//! 
//! ```json
//! {
//!     "tauri": {
//!         "allowlist": {
//!             "notification": {
//!                 "all": true // enable all notification APIs
//!             }
//!         }
//!     }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.

use serde::{Deserialize, Serialize};

/// Checks if the permission to send notifications is granted.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::notification;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let is_granted = notification::is_permission_granted().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn is_permission_granted() -> crate::Result<bool> {
    let raw = inner::isPermissionGranted().await?;

    Ok(serde_wasm_bindgen::from_value(raw)?)
}

/// Requests the permission to send notifications.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::notification;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let perm = notification::request_permission().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn request_permission() -> crate::Result<Permission> {
    let raw = inner::requestPermission().await?;

    Ok(serde_wasm_bindgen::from_value(raw)?)
}

/// Possible permission values.
#[derive(Debug, Deserialize, Default, Clone, Copy, PartialEq, Eq)]
pub enum Permission {
    #[default]
    #[serde(rename = "default")]
    Default,
    #[serde(rename = "granted")]
    Granted,
    #[serde(rename = "denied")]
    Denied,
}

/// The desktop notification definition.
///
/// Allows you to construct a Notification data and send it.
#[derive(Debug, Default, Serialize)]
pub struct Notification<'a> {
    body: Option<&'a str>,
    title: Option<&'a str>,
    icon: Option<&'a str>,
}

impl<'a> Notification<'a> {
    pub fn new() -> Self {
        Self::default()
    }

    /// Sets the notification title.
    pub fn set_title(&mut self, title: &'a str) {
        self.title = Some(title);
    }

    /// Sets the notification body.
    pub fn set_body(&mut self, body: &'a str) {
        self.body = Some(body);
    }

    /// Sets the notification icon.
    pub fn set_icon(&mut self, icon: &'a str) {
        self.icon = Some(icon);
    }

    /// Shows the notification.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use tauri_sys::notification::Notification;
    ///
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// Notification::new()
    ///     .set_title("Tauri")
    ///     .set_body("Tauri is awesome!")
    ///     .show()?;
    /// # Ok(())
    /// # }
    /// ```
    #[inline(always)]
    pub fn show(&self) -> crate::Result<()> {
        inner::sendNotification(serde_wasm_bindgen::to_value(&self)?)?;

        Ok(())
    }
}

mod inner {
    use wasm_bindgen::{prelude::wasm_bindgen, JsValue};

    #[wasm_bindgen(module = "/src/notification.js")]
    extern "C" {
        #[wasm_bindgen(catch)]
        pub async fn isPermissionGranted() -> Result<JsValue, JsValue>;
        #[wasm_bindgen(catch)]
        pub async fn requestPermission() -> Result<JsValue, JsValue>;
        #[wasm_bindgen(catch)]
        pub fn sendNotification(notification: JsValue) -> Result<(), JsValue>;
    }
}