Skip to content

Commit 5cf720a

Browse files
authored
feat: add on_dismissed support (#27)
1 parent b9e9d1b commit 5cf720a

File tree

5 files changed

+88
-17
lines changed

5 files changed

+88
-17
lines changed

.changes/changefile.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-winrt-notification": patch
3+
---
4+
5+
Add `Toast::on_dismissed` handler.

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"githubPullRequests.upstreamRemote": "never"
3+
}

README.md

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
# winrt-notification
22

3-
[![license](https://img.shields.io/crates/l/winrt-notification.svg)](https://crates.io/crates/winrt-notification/)
4-
[![version](https://img.shields.io/crates/v/winrt-notification.svg)](https://crates.io/crates/winrt-notification/)
5-
[![Build Status](https://img.shields.io/appveyor/ci/allenbenz/winrt-notification.svg)](https://ci.appveyor.com/project/allenbenz/winrt-notification)
3+
[![license](https://img.shields.io/crates/l/tauri-winrt-notification.svg)](https://crates.io/crates/tauri-winrt-notification/)
4+
[![documentation](https://img.shields.io/crates/v/tauri-winrt-notification?style=flat-square)](https://docs.rs/tauri-winrt-notification)
5+
66

77
An incomplete wrapper over the WinRT toast api
88

99
Tested in Windows 10 and 8.1. Untested in Windows 8, might work.
1010

11-
[0.5 Documentation](https://allenbenz.github.io/winrt-notification/0_5_0/winrt_notification/index.html)
12-
13-
[0.2 Documentation](https://allenbenz.github.io/winrt-notification/0_2_0/winrt_notification/index.html)
14-
1511
Todo:
1612
* Add support for Adaptive Content
17-
* Add support for Actions
1813

1914
Known Issues:
2015
* Will not work for Windows 7.
@@ -27,14 +22,14 @@ Limitations:
2722
```toml
2823
#Cargo.toml
2924
[dependencies]
30-
winrt-notification = "0.5.1"
25+
tauri-winrt-notification = "0.5.1"
3126
```
3227

3328
## Examples
3429

3530
```rust
3631
extern crate winrt_notification;
37-
use winrt_notification::{Duration, Sound, Toast};
32+
use tauri_winrt_notification::{Duration, Sound, Toast};
3833

3934
fn main() {
4035
Toast::new(Toast::POWERSHELL_APP_ID)
@@ -50,7 +45,7 @@ fn main() {
5045
```rust
5146
extern crate winrt_notification;
5247
use std::path::Path;
53-
use winrt_notification::{IconCrop, Toast};
48+
use tauri_winrt_notification::{IconCrop, Toast};
5449

5550
fn main() {
5651
Toast::new("Your AppUserModeId")

examples/simple.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
use std::{process::exit, thread::sleep, time::Duration as StdDuration};
77

8-
use tauri_winrt_notification::{Duration, Sound, Toast};
8+
use tauri_winrt_notification::{Duration, Sound, Toast, ToastDismissalReason};
99

1010
fn main() {
1111
Toast::new(Toast::POWERSHELL_APP_ID)
@@ -22,8 +22,18 @@ fn main() {
2222
})
2323
.add_button("Yes", "yes")
2424
.add_button("No", "no")
25+
.on_dismissed(|reason| {
26+
match reason {
27+
Some(ToastDismissalReason::UserCanceled) => println!("UserCanceled"),
28+
Some(ToastDismissalReason::ApplicationHidden) => println!("ApplicationHidden"),
29+
Some(ToastDismissalReason::TimedOut) => println!("TimedOut"),
30+
_ => println!("Unknown"),
31+
}
32+
exit(0)
33+
})
2534
.show()
2635
.expect("unable to send notification");
36+
2737
println!("Waiting 10 seconds for the notification to be clicked...");
2838
sleep(StdDuration::from_secs(10));
2939
println!("The notification wasn't clicked!");

src/lib.rs

+63-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//! Todo:
1111
//!
1212
//! * Add support for Adaptive Content
13-
//! * Add support for Actions
1413
//!
1514
//! Known Issues:
1615
//!
@@ -36,7 +35,9 @@ use windows::{
3635
core::{IInspectable, Interface},
3736
Data::Xml::Dom::XmlDocument,
3837
Foundation::TypedEventHandler,
39-
UI::Notifications::{ToastActivatedEventArgs, ToastNotificationManager},
38+
UI::Notifications::{
39+
ToastActivatedEventArgs, ToastDismissedEventArgs, ToastNotificationManager,
40+
},
4041
};
4142

4243
use std::fmt::Display;
@@ -47,6 +48,14 @@ use std::str::FromStr;
4748
pub use windows::core::{Error, Result, HSTRING};
4849
pub use windows::UI::Notifications::ToastNotification;
4950

51+
/// `ToastDismissalReason` is a struct representing the reason a toast notification was dismissed.
52+
///
53+
/// Variants:
54+
/// - `UserCanceled`: The user explicitly dismissed the toast notification.
55+
/// - `ApplicationHidden`: The application hid the toast notification programmatically.
56+
/// - `TimedOut`: The toast notification was dismissed because it timed out.
57+
pub use windows::UI::Notifications::ToastDismissalReason;
58+
5059
pub struct Toast {
5160
duration: String,
5261
title: String,
@@ -57,6 +66,7 @@ pub struct Toast {
5766
app_id: String,
5867
scenario: String,
5968
on_activated: Option<TypedEventHandler<ToastNotification, IInspectable>>,
69+
on_dismissed: Option<TypedEventHandler<ToastNotification, ToastDismissedEventArgs>>,
6070
buttons: Vec<Button>,
6171
}
6272

@@ -276,6 +286,7 @@ impl Toast {
276286
app_id: app_id.to_string(),
277287
scenario: String::new(),
278288
on_activated: None,
289+
on_dismissed: None,
279290
buttons: Vec::new(),
280291
}
281292
}
@@ -322,7 +333,7 @@ impl Toast {
322333
Duration::Long => "duration=\"long\"",
323334
Duration::Short => "duration=\"short\"",
324335
}
325-
.to_owned();
336+
.to_string();
326337
self
327338
}
328339

@@ -337,7 +348,7 @@ impl Toast {
337348
Scenario::Reminder => "scenario=\"reminder\"",
338349
Scenario::IncomingCall => "scenario=\"incomingCall\"",
339350
}
340-
.to_owned();
351+
.to_string();
341352
self
342353
}
343354

@@ -391,7 +402,7 @@ impl Toast {
391402
pub fn image(mut self, source: &Path, alt_text: &str) -> Toast {
392403
if !is_newer_than_windows81() {
393404
// win81 cannot have more than 1 image and shows nothing if there is more than that
394-
self.images = "".to_owned();
405+
self.images = String::new();
395406
}
396407
self.images = format!(
397408
r#"{}<image id="1" src="file:///{}" alt="{}" />"#,
@@ -459,6 +470,49 @@ impl Toast {
459470
None
460471
}
461472

473+
/// Set the function to be called when the toast is dismissed
474+
/// `f` will be called with the reason the toast was dismissed.
475+
/// If the toast was dismissed by the user, the reason will be `ToastDismissalReason::UserCanceled`.
476+
/// If the toast was dismissed by the application, the reason will be `ToastDismissalReason::ApplicationHidden`.
477+
/// If the toast was dismissed because it timed out, the reason will be `ToastDismissalReason::TimedOut`.
478+
/// If the reason is unknown, the reason will be `None`.
479+
///
480+
/// # Example
481+
/// ```rust
482+
/// use tauri_winrt_notification::{Toast, ToastDismissalReason};
483+
///
484+
/// let toast = Toast::new(Toast::POWERSHELL_APP_ID);
485+
/// toast.on_dismissed(|reason| {
486+
/// match reason {
487+
/// Some(ToastDismissalReason::UserCanceled) => println!("UserCanceled"),
488+
/// Some(ToastDismissalReason::ApplicationHidden) => println!("ApplicationHidden"),
489+
/// Some(ToastDismissalReason::TimedOut) => println!("TimedOut"),
490+
/// _ => println!("Unknown"),
491+
/// }
492+
/// Ok(())
493+
/// }).show().expect("notification failed");
494+
/// ```
495+
pub fn on_dismissed<F: Fn(Option<ToastDismissalReason>) -> Result<()> + Send + 'static>(
496+
mut self,
497+
f: F,
498+
) -> Self {
499+
self.on_dismissed = Some(TypedEventHandler::new(move |_, args| {
500+
f(Self::get_dismissed_reason(args))
501+
}));
502+
self
503+
}
504+
505+
fn get_dismissed_reason(
506+
args: &Option<ToastDismissedEventArgs>,
507+
) -> Option<ToastDismissalReason> {
508+
if let Some(args) = args {
509+
if let Ok(reason) = args.Reason() {
510+
return Some(reason);
511+
}
512+
}
513+
None
514+
}
515+
462516
fn create_template(&self) -> windows::core::Result<ToastNotification> {
463517
//using this to get an instance of XmlDocument
464518
let toast_xml = XmlDocument::new()?;
@@ -520,6 +574,10 @@ impl Toast {
520574
toast_template.Activated(handler)?;
521575
}
522576

577+
if let Some(handler) = &self.on_dismissed {
578+
toast_template.Dismissed(handler)?;
579+
}
580+
523581
let toast_notifier =
524582
ToastNotificationManager::CreateToastNotifierWithId(&HSTRING::from(&self.app_id))?;
525583

0 commit comments

Comments
 (0)