Skip to main content

libnotify_rs/wrappers/
builder.rs

1use crate::{
2    api::{
3        errors::LibnotifyError,
4        notification::{HintValue, Notification, Timeout, Urgency},
5    },
6    wrappers::context::LibnotifyContext,
7};
8
9/// Higher level abstraction of `Notification`. Allow for builder pattern notification construction.
10/// Requires `LibnotifyContext`
11pub struct NotificationBuilder<'a> {
12    notification: Notification,
13    _context: &'a LibnotifyContext,
14}
15
16impl<'a> NotificationBuilder<'a> {
17    /// Create new NotificationBuilder, with given context.
18    ///
19    /// # Errors
20    ///
21    /// This function can return LibnotifyError::{NewNotificationError, NulError}
22    ///
23    /// # Example
24    /// ```
25    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
26    ///
27    /// // Builder is recommended way to interact with libnotify notifications
28    ///
29    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
30    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
31    ///
32    ///     let notification_builder = NotificationBuilder::new(
33    ///         "Remember about your coffee!",
34    ///         "Only idiots forget about coffee!",
35    ///         None,
36    ///         &ctx,
37    ///     )?;
38    ///
39    ///     // you don't need to uninitialize libnotify, cause context already does that!
40    ///
41    ///     Ok(())
42    /// }
43    ///
44    /// ```
45    pub fn new<T, Y>(
46        summary: &str,
47        body: T,
48        icon: Y,
49        context: &'a LibnotifyContext,
50    ) -> Result<Self, Box<dyn std::error::Error>>
51    where
52        T: Into<Option<&'a str>>,
53        Y: Into<Option<&'a str>>,
54    {
55        let notification = Notification::new(summary, body, icon)?;
56
57        Ok(Self {
58            notification,
59            _context: context,
60        })
61    }
62
63    /// Sets app name for this specific notification.
64    ///
65    /// # Errors
66    /// This function can return LibnotifyError::{NulError}
67    ///
68    /// # Example
69    /// ```ignore(Small example)
70    /// let notification_builder = NotificationBuilder::new(
71    ///     "Remember about your coffee!",
72    ///     "Only idiots forget about coffee!",
73    ///     None,
74    ///     &ctx,
75    /// )?
76    /// .set_app_name("Other app name");
77    /// ```
78    pub fn set_app_name<T: Into<Option<&'a str>>>(
79        mut self,
80        app_name: T,
81    ) -> Result<Self, LibnotifyError> {
82        if let Some(app_name) = app_name.into() {
83            self.notification.set_app_name(app_name)?;
84        }
85
86        Ok(self)
87    }
88
89    /// Sets app icon fot this specific notification.
90    ///
91    /// # Errors
92    /// This function can return LibnotifyError::{NulError}
93    ///
94    /// # Example
95    /// ```ignore(Small example)
96    /// let notification_builder = NotificationBuilder::new(
97    ///     "Remember about your coffee!",
98    ///     "Only idiots forget about coffee!",
99    ///     None,
100    ///     &ctx,
101    /// )?
102    /// .set_app_icon("STOCK-HOME")?;
103    /// ```
104    pub fn set_app_icon<T: Into<Option<&'a str>>>(
105        mut self,
106        app_icon: T,
107    ) -> Result<Self, LibnotifyError> {
108        if let Some(app_icon) = app_icon.into() {
109            self.notification.set_app_icon(app_icon)?;
110        }
111
112        Ok(self)
113    }
114
115    /// Sets category for this specific notification
116    ///
117    /// # Errors
118    /// This function can return LibnotifyError::{NulError}
119    pub fn set_category<T: Into<Option<&'a str>>>(
120        mut self,
121        category: T,
122    ) -> Result<Self, LibnotifyError> {
123        if let Some(category) = category.into() {
124            self.notification.set_category(category)?;
125        }
126
127        Ok(self)
128    }
129
130    /// Set hint for this specific notification
131    /// # Errors
132    /// This function can return LibnotifyError::{NulError, AllocationError}
133    pub fn set_hint(mut self, key: &str, value: HintValue) -> Result<Self, LibnotifyError> {
134        self.notification.set_hint(key, value)?;
135        Ok(self)
136    }
137
138    /// Set timeout until close
139    ///
140    /// # Example
141    /// ```
142    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
143    ///
144    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
145    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
146    ///
147    ///     let notification_builder = NotificationBuilder::new(
148    ///         "Remember about your coffee!",
149    ///         "Only idiots forget about coffee!",
150    ///         None,
151    ///         &ctx,
152    ///     )?
153    ///     .set_timeout(libnotify_rs::api::notification::Timeout::Never);
154    ///
155    ///     Ok(())
156    /// }
157    /// ```
158    pub fn set_timeout<T: Into<Option<Timeout>>>(mut self, timeout: T) -> Self {
159        if let Some(timeout) = timeout.into() {
160            self.notification.set_timeout(timeout);
161        }
162
163        self
164    }
165
166    /// Set notification urgency level
167    ///
168    /// # Example
169    /// ```
170    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
171    ///
172    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
173    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
174    ///
175    ///     let notification_builder = NotificationBuilder::new(
176    ///         "Remember about your coffee!",
177    ///         "Only idiots forget about coffee!",
178    ///         None,
179    ///         &ctx,
180    ///     )?
181    ///     .set_urgency(libnotify_rs::api::notification::Urgency::Critical);
182    ///
183    ///     Ok(())
184    /// }
185    /// ```
186    pub fn set_urgency<T: Into<Option<Urgency>>>(mut self, urgency: T) -> Self {
187        if let Some(urgency) = urgency.into() {
188            self.notification.set_urgency(urgency);
189        }
190
191        self
192    }
193
194    /// Add callback
195    ///
196    /// # Errors
197    /// This function can return LibnotifyError::NulError
198    ///
199    /// # Example
200    /// ```
201    ///
202    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
203    ///
204    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
205    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
206    ///
207    ///     let notification_builder = NotificationBuilder::new(
208    ///         "Remember about your coffee!",
209    ///         "Only idiots forget about coffee!",
210    ///         None,
211    ///         &ctx,
212    ///     )?
213    ///     .add_action("default", "super cool action", |action| {
214    ///         println!("Action: {} was run!", action);
215    ///     });
216    ///
217    ///     Ok(())
218    /// }
219    /// ```
220    pub fn add_action<F>(
221        mut self,
222        action: &str,
223        label: &str,
224        callback: F,
225    ) -> Result<Self, LibnotifyError>
226    where
227        F: Fn(&str) + 'static,
228    {
229        self.notification.add_action(action, label, callback)?;
230        Ok(self)
231    }
232
233    /// Show notification
234    ///
235    /// Uses `&self` borrow, so you can use this object later, after showing.
236    ///
237    /// # Errors
238    /// This function can return LibnotifyError::{GerrorError, AllocationError}
239    ///
240    /// # Example
241    /// ```no_run(No notification daemon on CI)
242    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
243    ///
244    /// /// Builder is recommended way to interact with libnotify notifications
245    ///
246    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
247    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
248    ///
249    ///     let notification_builder = NotificationBuilder::new(
250    ///         "Remember about your coffee!",
251    ///         "Only idiots forget about coffee!",
252    ///         None,
253    ///         &ctx,
254    ///     )?
255    ///     .set_urgency(libnotify_rs::api::notification::Urgency::Critical)
256    ///     .set_timeout(libnotify_rs::api::notification::Timeout::Never)
257    ///     .set_category("Coffee")?;
258    ///
259    ///     notification_builder.show()?;
260    ///
261    ///     Ok(())
262    /// }
263    /// ```
264    pub fn show(&self) -> Result<(), LibnotifyError> {
265        self.notification.show()?;
266        Ok(())
267    }
268
269    /// Close notification synchronously.
270    ///
271    /// Uses `&self` borrow, so you can use this object later, after closing.
272    ///
273    /// # Errors
274    /// This function can return LibnotifyError::{GerrorError, AllocationError}
275    ///
276    /// # Example
277    /// ```no_run(No notification daemon on CI)
278    /// use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
279    ///
280    /// /// Builder is recommended way to interact with libnotify notifications
281    ///
282    /// fn main() -> Result<(), Box<dyn std::error::Error>> {
283    ///     let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context
284    ///
285    ///     let notification_builder = NotificationBuilder::new(
286    ///         "Remember about your coffee!",
287    ///         "Only idiots forget about coffee!",
288    ///         None,
289    ///         &ctx,
290    ///     )?
291    ///     .set_urgency(libnotify_rs::api::notification::Urgency::Critical)
292    ///     .set_timeout(libnotify_rs::api::notification::Timeout::Never)
293    ///     .set_category("Coffee")?;
294    ///
295    ///     notification_builder.show()?;
296    ///     notification_builder.close()?;
297    ///     Ok(())
298    /// }
299    /// ```
300    pub fn close(&self) -> Result<(), LibnotifyError> {
301        self.notification.close()?;
302        Ok(())
303    }
304}