From 7966726534b321136e9426cda1ed78117fbf6c2d Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 1 Oct 2026 16:31:16 +0200 Subject: [PATCH 1/4] feat: add libnotify context --- src/context.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 41 insertions(+) create mode 100644 src/context.rs diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 0000000..fb0ab63 --- /dev/null +++ b/src/context.rs @@ -0,0 +1,40 @@ +use crate::functions::{init, is_initted, set_app_icon, set_app_name, uninit}; + +pub struct LibnotifyContext {} + +static IS_CONTEXT_CREATED: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); + +impl LibnotifyContext { + pub fn new(app_name: &str) -> Result> { + if IS_CONTEXT_CREATED.swap(true, std::sync::atomic::Ordering::SeqCst) { + return Err("You can create only one context at a time".into()); + } + + if !is_initted() { + init(app_name)?; + } + + Ok(Self {}) + } + + pub fn set_new_name(&self, app_name: &str) -> Result<(), std::ffi::NulError> { + set_app_name(app_name)?; + Ok(()) + } + + pub fn set_app_icon(&self, app_icon: &str) -> Result<(), std::ffi::NulError> { + set_app_icon(app_icon)?; + Ok(()) + } +} + +impl Drop for LibnotifyContext { + fn drop(&mut self) { + if is_initted() { + uninit(); + + IS_CONTEXT_CREATED.store(false, std::sync::atomic::Ordering::SeqCst); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index bd067f8..bed7767 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +pub mod context; pub mod functions; mod libnotify; pub mod notification; From 744efe8ec9fea87814741ac71f87398a906c52f2 Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 1 Oct 2026 20:48:56 +0200 Subject: [PATCH 2/4] feat: add notifaction builder --- src/builder.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/notification.rs | 2 +- 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/builder.rs diff --git a/src/builder.rs b/src/builder.rs new file mode 100644 index 0000000..2ae379a --- /dev/null +++ b/src/builder.rs @@ -0,0 +1,85 @@ +use crate::{ + context::LibnotifyContext, + notification::{HintValue, Notification, Timeout, Urgency}, +}; + +pub struct NotificationBuilder<'a> { + notification: Notification, + _context: &'a LibnotifyContext, +} + +impl<'a> NotificationBuilder<'a> { + pub fn new( + summary: &str, + body: T, + icon: Y, + context: &'a LibnotifyContext, + ) -> Result> + where + T: Into>, + Y: Into>, + { + let notification = Notification::new(summary, body, icon)?; + + Ok(Self { + notification, + _context: context, + }) + } + + pub fn set_app_name(mut self, app_name: &str) -> Result { + self.notification.set_app_name(app_name)?; + Ok(self) + } + + pub fn set_app_icon(mut self, app_icon: &str) -> Result { + self.notification.set_app_icon(app_icon)?; + Ok(self) + } + pub fn set_category(mut self, category: &str) -> Result { + self.notification.set_category(category)?; + Ok(self) + } + + pub fn set_hint( + mut self, + key: &str, + value: HintValue, + ) -> Result> { + self.notification.set_hint(key, value)?; + Ok(self) + } + + pub fn set_timeout(mut self, timeout: Timeout) -> Self { + self.notification.set_timeout(timeout); + self + } + + pub fn set_urgency(mut self, urgency: Urgency) -> Self { + self.notification.set_urgency(urgency); + self + } + + pub fn add_action( + mut self, + action: &str, + label: &str, + callback: F, + ) -> Result> + where + F: Fn(&str) + 'static, + { + self.notification.add_action(action, label, callback)?; + Ok(self) + } + + pub fn show(&self) -> Result<(), Box> { + self.notification.show()?; + Ok(()) + } + + pub fn close(&self) -> Result<(), Box> { + self.notification.close()?; + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index bed7767..8029fef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +pub mod builder; pub mod context; pub mod functions; mod libnotify; diff --git a/src/notification.rs b/src/notification.rs index fb51d41..e195bd9 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -162,7 +162,7 @@ impl<'a> Notification { /// `set_app_icon()`. /// /// Available since: 0.8.4 - pub fn set_app_icon(&mut self, app_icon: &str) -> Result<(), Box> { + pub fn set_app_icon(&mut self, app_icon: &str) -> Result<(), std::ffi::NulError> { let app_icon_c = std::ffi::CString::new(app_icon)?; unsafe { notify_notification_set_app_icon(self.inner, app_icon_c.as_ptr()) }; From 5f0b2f199a9d5dd479d32c0b43edda3a3966b44d Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 1 Oct 2026 21:00:23 +0200 Subject: [PATCH 3/4] feat: add example for builder --- examples/builder.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 examples/builder.rs diff --git a/examples/builder.rs b/examples/builder.rs new file mode 100644 index 0000000..75add19 --- /dev/null +++ b/examples/builder.rs @@ -0,0 +1,23 @@ +use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext}; + +/// Builder is recommended way to interact with libnotify notifications + +fn main() -> Result<(), Box> { + let ctx = LibnotifyContext::new("Coffee addicted reminder")?; // builder requires context + + let notification_builder = NotificationBuilder::new( + "Remember about your coffee!", + "Only idiots forget about coffee!", + None, + &ctx, + )? + .set_urgency(libnotify_rs::notification::Urgency::Critical) + .set_timeout(libnotify_rs::notification::Timeout::Never) + .set_category("Coffee")?; + + notification_builder.show()?; + + // you don't need to uninitialize libnotify, cause context already does that! + + Ok(()) +} From 6cbb7524cf571253ad090b96c8cf8a4f60e560a2 Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 1 Oct 2026 21:22:40 +0200 Subject: [PATCH 4/4] chore: version bump --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7020c81..4138772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -247,7 +247,7 @@ dependencies = [ [[package]] name = "libnotify-rs" -version = "0.1.0" +version = "0.2.0" dependencies = [ "bindgen", "glib", diff --git a/Cargo.toml b/Cargo.toml index 3526eea..ea5c5ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libnotify-rs" -version = "0.1.0" +version = "0.2.0" edition = "2024" authors = [ "szymon_jozef"] description = "Rust bindings for libnotify"