diff --git a/src/main.rs b/src/main.rs index 948c60d..c7ffa05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,10 @@ use notification::{print_notif, to_notif}; use futures_util::stream::TryStreamExt; use zbus::{Connection, Result}; -const SERVER_NAME: &str = "SNot"; -const VENDOR: &str = "candifloss.cc"; -const VERSION: &str = "0.1.0"; -const SPEC_VERSION: &str = "1.0"; +const SERVER_NAME: &str = "SNot"; // Server software name +const VENDOR: &str = "candifloss.cc"; // Server sw author +const VERSION: &str = "0.1.0"; // Server version +const SPEC_VERSION: &str = "0.42"; // DBus Spec version #[tokio::main] async fn main() -> Result<()> { @@ -43,7 +43,6 @@ async fn main() -> Result<()> { let notif = to_notif(&msg_body)?; // Print the notif print_notif(¬if); - println!("{}\n", notif.urgency()); // Done. Respond to the client with a notification ID let notification_id: u32 = 1; // This could be incremented or generated. Do it l8r connection.reply(&msg, ¬ification_id).await?; // The client will disconnect when it gets this response diff --git a/src/notification.rs b/src/notification.rs index fe600ac..1b7a76c 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -1,22 +1,30 @@ -use std::collections::{btree_map::Range, HashMap}; +use std::collections::HashMap; use zbus::{message::Body, Result}; use zvariant::OwnedValue; +// A notificaion object pub struct Notification { - // A notificaion object - app_name: String, // The application that sent the notification - replace_id: u32, // (Optional) ID of an existing notification to be updated, replaced by this - icon: String, // See icon specifications: https://specifications.freedesktop.org/notification-spec/latest/icons-and-images.html - summary: String, // Notification title - body: String, // Notification content/body - actions: Vec, // Action requests that can be sent back to the client - - hints: HashMap, // Extra useful data - notif type, urgency, sound file, icon data, etc. - expir_timeout: i32, // Seconds till this notif expires. Optional + // The application that sent the notification + app_name: String, + // (Optional) ID of an existing notification to be updated, replaced by this + replace_id: u32, + // See icon specifications: https://specifications.freedesktop.org/notification-spec/latest/icons-and-images.html + icon: String, + // Notification title + summary: String, + // Notification content/body + body: String, + // Action requests that can be sent back to the client - "Reply," "Mark as Read," "Play/Pause/Next," "Snooze/Dismiss," etc. + actions: Vec, + // Extra useful data - notif type, urgency, sound file, icon data, etc. + hints: HashMap, + // Seconds till this notif expires. Optional + expir_timeout: i32, } impl Notification { + // Obtain urgency pub fn urgency(&self) -> String { - // Obtain urgency match self.hints.get("urgency") { Some(value) => { // Attempt to convert OwnedValue to u8 @@ -31,20 +39,43 @@ impl Notification { } } - pub fn actions(&self) -> HashMap { - let mut acts: HashMap; - for i in Range(self.actions.len()) { - + // Key:Val pairs of actions + pub fn actions(&self) -> Vec<(String, String)> { + let mut actions: Vec<(String, String)> = vec![]; + let acts = &self.actions; + let act_len = acts.len(); + let mut i = 0; + while i < act_len { + // Action ID, used by the sender to id the clicked action + let action_id = &acts[i]; + // Localised human-readable string that describes the label + let action_label = &acts[i + 1]; + // Pair of (id: label) + let action_pair = (action_id.to_owned(), action_label.to_owned()); + // Add it to the Vec + actions.push(action_pair); + i += 2; + } + actions + } + + // Default action + pub fn default_action(&self) -> Option<(String, String)> { + if self.actions().is_empty() { + None + } else { + Some(self.actions()[0].clone()) } } } +// Convert the DBus message body into Notification pub fn to_notif(msg_body: &Body) -> Result { - // Convert the DBus message body into Notification + // Deserialized body into a tuple let (app_name, replace_id, icon, summary, body, actions, hints, expir_timeout) = - msg_body.deserialize()?; // Deserialized into a tuple + msg_body.deserialize()?; + // Make a Notification object from the obtained tuple Ok(Notification { - // Make a Notification object from the obtained tuple app_name, replace_id, icon, @@ -62,10 +93,22 @@ pub fn print_notif(notif: &Notification) { println!("Icon: {0}", notif.icon); println!("Summary: {0}", notif.summary); println!("Body: {0}", notif.body); - println!("Actions: {0:?}", notif.actions); + // println!("Actions: {0:?}", notif.actions); + println!("Actions:"); + if notif.actions().is_empty() { + println!("\tNone"); + } else { + for actn in notif.actions() { + println!("\t{}: {},", actn.0, actn.1); + } + } + if let Some(action) = notif.default_action() { + println!("Default action:\t{}:{}", action.0, action.1); + } println!("Hints:"); for (key, value) in ¬if.hints { - println!(" {key}: {value:?}"); + println!("\t{key}: {value:?}"); } + println!("Urgency:{}", notif.urgency()); println!("Expiration Timeout: {0} seconds", notif.expir_timeout); }