diff --git a/examples/click.rs b/examples/click.rs new file mode 100644 index 0000000..00de49f --- /dev/null +++ b/examples/click.rs @@ -0,0 +1,17 @@ +use mac_notification_sys::*; + +fn main() { + let response = send_notification( + "clickable notification", + None, + "click me", + Some(Notification::new().wait_for_click(true)), + ) + .unwrap(); + + if matches!(response, NotificationResponse::Click) { + println!("Clicked the notification"); + } else { + println!("No interaction"); + } +} diff --git a/objc/notify.h b/objc/notify.h index cf1440e..7904237 100644 --- a/objc/notify.h +++ b/objc/notify.h @@ -31,6 +31,7 @@ BOOL installNSBundleHook(void) { @interface NotificationCenterDelegate: NSObject @property(nonatomic, assign) BOOL keepRunning; +@property(nonatomic, assign) BOOL waitForClick; @property(nonatomic, retain) NSDictionary* actionData; @end @@ -40,7 +41,7 @@ BOOL installNSBundleHook(void) { - (void)userNotificationCenter:(NSUserNotificationCenter*)center didDeliverNotification:(NSUserNotification*)notification { // Stop running if we're not expecting a response - if (!notification.hasActionButton && !notification.hasReplyButton) { + if (!notification.hasActionButton && !notification.hasReplyButton && !self.waitForClick) { self.keepRunning = NO; } } diff --git a/objc/notify.m b/objc/notify.m index 65c3edb..6f75647 100644 --- a/objc/notify.m +++ b/objc/notify.m @@ -104,6 +104,12 @@ BOOL setApplication(NSString* newbundleIdentifier) { userNotification.responsePlaceholder = options[@"mainButtonLabel"]; } + // Wait for click + if (options[@"click"] && ![options[@"click"] isEqualToString:@"yes"]) { + ncDelegate.keepRunning = YES; + ncDelegate.waitForClick = YES; + } + // Change the icon of the app in the notification if (options[@"appIcon"] && ![options[@"appIcon"] isEqualToString:@""]) { NSImage* icon = getImageFromURL(options[@"appIcon"]); diff --git a/src/notification.rs b/src/notification.rs index 34c85a0..c7701aa 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -72,6 +72,7 @@ pub struct Notification<'a> { pub(crate) delivery_date: Option, pub(crate) sound: Option, pub(crate) asynchronous: Option, + pub(crate) wait_for_click: Option, } impl<'a> Notification<'a> { @@ -230,6 +231,19 @@ impl<'a> Notification<'a> { self } + /// Allow waiting a response for notification click. + /// + /// # Example: + /// + /// ```no_run + /// # use mac_notification_sys::*; + /// let _ = Notification::new().wait_for_click(true); + /// ``` + pub fn wait_for_click(&mut self, click: bool) -> &mut Self { + self.wait_for_click = Some(click); + self + } + /// Convert the Notification to an Objective C NSDictionary pub(crate) fn to_dictionary(&self) -> Retained> { // TODO: If possible, find a way to simplify this so I don't have to manually convert struct to NSDictionary @@ -243,6 +257,7 @@ impl<'a> Notification<'a> { &*NSString::from_str("deliveryDate"), &*NSString::from_str("asynchronous"), &*NSString::from_str("sound"), + &*NSString::from_str("click"), ]; let (main_button_label, actions, is_response): (&str, &[&str], bool) = match &self.main_button { @@ -280,6 +295,11 @@ impl<'a> Notification<'a> { Some(true) => "yes", _ => "no", }), + // TODO: Same as above, if NSDictionary could support multiple types, this could be a boolean + NSString::from_str(match self.wait_for_click { + Some(true) => "yes", + _ => "no", + }), NSString::from_str(sound), ]; NSDictionary::from_retained_objects(keys, &vals)