use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Urgency {
Low = 0,
Normal = 1,
Critical = 2,
}
impl From<u8> for Urgency {
fn from(val: u8) -> Self {
match val {
0 => Urgency::Low,
2 => Urgency::Critical,
_ => Urgency::Normal,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Notification {
pub id: u32,
pub app_name: String,
pub app_icon: String,
pub summary: String,
pub body: String,
pub actions: Vec<(String, String)>,
pub urgency: Urgency,
pub timeout_ms: i32,
pub timestamp: SystemTime,
pub read: bool,
pub desktop_entry: Option<String>,
}
pub fn clean_markup(text: &str) -> String {
let mut result = String::with_capacity(text.len());
let mut in_tag = false;
for ch in text.chars() {
match ch {
'<' => in_tag = true,
'>' if in_tag => in_tag = false,
_ if !in_tag => result.push(ch),
_ => {}
}
}
result
.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace(""", "\"")
.replace("'", "'")
.replace("'", "'")
}
pub fn parse_actions(flat: &[String]) -> Vec<(String, String)> {
flat.chunks(2)
.filter_map(|chunk| {
if chunk.len() == 2 {
Some((chunk[0].clone(), chunk[1].clone()))
} else {
None
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn urgency_from_u8() {
assert_eq!(Urgency::from(0), Urgency::Low);
assert_eq!(Urgency::from(1), Urgency::Normal);
assert_eq!(Urgency::from(2), Urgency::Critical);
assert_eq!(Urgency::from(255), Urgency::Normal);
}
#[test]
fn parse_actions_pairs() {
let flat = vec![
"reply".into(),
"Reply".into(),
"dismiss".into(),
"Dismiss".into(),
];
let actions = parse_actions(&flat);
assert_eq!(actions.len(), 2);
assert_eq!(actions[0], ("reply".into(), "Reply".into()));
}
#[test]
fn parse_actions_odd_length() {
let flat = vec!["only-one".into()];
let actions = parse_actions(&flat);
assert!(actions.is_empty());
}
#[test]
fn clean_markup_strips_tags() {
assert_eq!(clean_markup("<b>bold</b> text"), "bold text");
assert_eq!(
clean_markup(r#"<a href="http://example.com">link</a>"#),
"link"
);
assert_eq!(clean_markup("line1<br>line2"), "line1line2");
}
#[test]
fn clean_markup_decodes_entities() {
assert_eq!(clean_markup("a & b"), "a & b");
assert_eq!(clean_markup("<user@mail.com>"), "<user@mail.com>");
assert_eq!(clean_markup(""hello""), "\"hello\"");
assert_eq!(clean_markup("it's"), "it's");
}
#[test]
fn clean_markup_combined() {
assert_eq!(
clean_markup("From: <b>Alice</b> <alice@example.com>"),
"From: Alice <alice@example.com>"
);
}
}