Merge pull request #1 from szymon-jozef/feat/builder

feat/builder
This commit is contained in:
Szymon
2026-10-01 21:25:27 +02:00
committed by GitHub
7 changed files with 153 additions and 3 deletions

2
Cargo.lock generated
View File

@@ -247,7 +247,7 @@ dependencies = [
[[package]]
name = "libnotify-rs"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"bindgen",
"glib",

View File

@@ -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"

23
examples/builder.rs Normal file
View File

@@ -0,0 +1,23 @@
use libnotify_rs::{builder::NotificationBuilder, context::LibnotifyContext};
/// Builder is recommended way to interact with libnotify notifications
fn main() -> Result<(), Box<dyn std::error::Error>> {
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(())
}

85
src/builder.rs Normal file
View File

@@ -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<T, Y>(
summary: &str,
body: T,
icon: Y,
context: &'a LibnotifyContext,
) -> Result<Self, Box<dyn std::error::Error>>
where
T: Into<Option<&'a str>>,
Y: Into<Option<&'a str>>,
{
let notification = Notification::new(summary, body, icon)?;
Ok(Self {
notification,
_context: context,
})
}
pub fn set_app_name(mut self, app_name: &str) -> Result<Self, std::ffi::NulError> {
self.notification.set_app_name(app_name)?;
Ok(self)
}
pub fn set_app_icon(mut self, app_icon: &str) -> Result<Self, std::ffi::NulError> {
self.notification.set_app_icon(app_icon)?;
Ok(self)
}
pub fn set_category(mut self, category: &str) -> Result<Self, std::ffi::NulError> {
self.notification.set_category(category)?;
Ok(self)
}
pub fn set_hint(
mut self,
key: &str,
value: HintValue,
) -> Result<Self, Box<dyn std::error::Error>> {
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<F>(
mut self,
action: &str,
label: &str,
callback: F,
) -> Result<Self, Box<dyn std::error::Error>>
where
F: Fn(&str) + 'static,
{
self.notification.add_action(action, label, callback)?;
Ok(self)
}
pub fn show(&self) -> Result<(), Box<dyn std::error::Error>> {
self.notification.show()?;
Ok(())
}
pub fn close(&self) -> Result<(), Box<dyn std::error::Error>> {
self.notification.close()?;
Ok(())
}
}

40
src/context.rs Normal file
View File

@@ -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<LibnotifyContext, Box<dyn std::error::Error>> {
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);
}
}
}

View File

@@ -3,6 +3,8 @@
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub mod builder;
pub mod context;
pub mod functions;
mod libnotify;
pub mod notification;

View File

@@ -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<dyn std::error::Error>> {
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()) };