Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions examples/urgency.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
#[cfg(any(target_os = "windows", target_os = "macos"))]
#[cfg(target_os = "macos")]
fn main() {
println!("this is an xdg only feature")
println!("Urgency is not supported on macOS")
}

#[cfg(all(unix, not(target_os = "macos")))]
#[cfg(any(all(unix, not(target_os = "macos")), target_os = "windows"))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
use notify_rust::{Notification, Urgency::*};
// use it this way

#[cfg(all(unix, not(target_os = "macos")))]
println!("Testing urgency on Linux/BSD (XDG)");
#[cfg(all(unix, not(target_os = "macos")))]
println!("Urgency is sent as a hint. Critical notifications should not timeout.\n");

#[cfg(target_os = "windows")]
println!("Testing urgency on Windows");
#[cfg(target_os = "windows")]
println!("Low/Normal → Default scenario, Critical → Reminder scenario (stays on screen)\n");

// Test all urgency levels
for urgency in &[Low, Normal, Critical] {
Notification::new()
let mut notification = Notification::new();
notification
.summary(&format!("Urgency {:?}", urgency))
.body("This notification uses hints")
.icon("firefox")
.urgency(*urgency)
.show()?;
.body("This notification demonstrates urgency levels")
.urgency(*urgency);

#[cfg(all(unix, not(target_os = "macos")))]
notification.icon("firefox");

notification.show()?;
}

Notification::new()
.body("Urgency from String")
.icon("dialog-warning")
.urgency("high".try_into()?)
.show()?;
// Test urgency from string
let mut notification = Notification::new();
notification
.summary("Urgency from String")
.body("This uses 'high' which maps to Critical")
.urgency("high".try_into()?);

#[cfg(all(unix, not(target_os = "macos")))]
notification.icon("dialog-warning");

notification.show()?;

Ok(())
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
//! | `fn auto_icon(...)`| ✔︎ | | |
//! | `fn hint(...)` | ✔︎ | ❌ | ❌ |
//! | `fn timeout(...)` | ✔︎ | | ✔︎ |
//! | `fn urgency(...)` | ✔︎ | ❌ | |
//! | `fn urgency(...)` | ✔︎ | ❌ | ✔︎ |
//! | `fn action(...)` | ✔︎ | | |
//! | `fn id(...)` | ✔︎ | | |
//! | `fn finalize(...)` | ✔︎ | ✔︎ | ✔︎ |
Expand Down
43 changes: 40 additions & 3 deletions src/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ pub struct Notification {
#[cfg(target_os = "windows")]
pub(crate) app_id: Option<String>,

#[cfg(target_os = "windows")]
pub(crate) urgency: Option<Urgency>,

#[cfg(all(unix, not(target_os = "macos")))]
pub(crate) bus: xdg::NotificationBus,

Expand Down Expand Up @@ -325,17 +328,50 @@ impl Notification {

/// Set the `urgency`.
///
/// Pick between Medium, Low and High.
/// Pick between Low, Normal, and Critical.
///
/// # Platform support
/// Most Desktops on linux and bsd are far too relaxed to pay any attention to this.
/// In macOS this does not exist
///
/// ## Linux/BSD (XDG)
/// Urgency is sent as a hint to the notification server. Most desktops are fairly relaxed
/// about urgency and may not change behavior significantly. Critical notifications are
/// intended to not timeout automatically.
///
/// ## Windows
/// Urgency is mapped to toast scenarios:
/// - `Low` and `Normal` → Default scenario (standard toast behavior)
/// - `Critical` → Reminder scenario (stays on screen until user dismisses)
///
/// ## macOS
/// Not currently supported.
#[cfg(all(unix, not(target_os = "macos")))]
pub fn urgency(&mut self, urgency: Urgency) -> &mut Notification {
self.hint(Hint::Urgency(urgency)); // TODO impl as T where T: Into<Urgency>
self
}

/// Set the `urgency`.
///
/// Pick between Low, Normal, and Critical.
///
/// # Platform support
///
/// ## Windows
/// Urgency is mapped to toast scenarios:
/// - `Low` and `Normal` → Default scenario (standard toast behavior)
/// - `Critical` → Reminder scenario (stays on screen until user dismisses)
///
/// ## Linux/BSD (XDG)
/// See the Unix implementation documentation.
///
/// ## macOS
/// Not currently supported.
#[cfg(target_os = "windows")]
pub fn urgency(&mut self, urgency: Urgency) -> &mut Notification {
self.urgency = Some(urgency);
self
}

/// Set `actions`.
///
/// To quote <http://www.galago-project.org/specs/notification/0.9/x408.html#command-notify>
Expand Down Expand Up @@ -514,6 +550,7 @@ impl Default for Notification {
id: None,
path_to_image: None,
app_id: None,
urgency: None,
}
}
}
15 changes: 14 additions & 1 deletion src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use winrt_notification::Toast;

pub use crate::{error::*, notification::Notification, timeout::Timeout};
pub use crate::{error::*, notification::Notification, timeout::Timeout, urgency::Urgency};

use std::{path::Path, str::FromStr};

Expand All @@ -22,6 +22,14 @@ pub(crate) fn show_notification(notification: &Notification) -> Result<()> {
}
};

// Map urgency to Windows toast scenario
// Low/Normal -> Default (standard behavior)
// Critical -> Reminder (stays on screen until dismissed, matching XDG spec)
let scenario = match notification.urgency {
Some(Urgency::Critical) => Some(winrt_notification::Scenario::Reminder),
Some(Urgency::Low) | Some(Urgency::Normal) | None => None, // Default scenario
};

let powershell_app_id = &Toast::POWERSHELL_APP_ID.to_string();
let app_id = &notification.app_id.as_ref().unwrap_or(powershell_app_id);
let mut toast = Toast::new(app_id)
Expand All @@ -30,6 +38,11 @@ pub(crate) fn show_notification(notification: &Notification) -> Result<()> {
.text2(&notification.body)
.sound(sound)
.duration(duration);

// Apply scenario if urgency was set
if let Some(scenario) = scenario {
toast = toast.scenario(scenario);
}
if let Some(image_path) = &notification.path_to_image {
toast = toast.image(Path::new(&image_path), "");
}
Expand Down
Loading