Skip to content

Commit

Permalink
Merge pull request #52 from h4llow3En/feature/fix-action-crash
Browse files Browse the repository at this point in the history
fix action crash
  • Loading branch information
hoodie authored Aug 11, 2023
2 parents 5c67376 + ba226cd commit b5cc2b3
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 112 deletions.
28 changes: 24 additions & 4 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@ BasedOnStyle: LLVM
UseTab: Never
IndentWidth: 4
TabWidth: 4
BreakBeforeBraces: Allman

AccessModifierOffset: -2
AlignTrailingComments: false
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakBeforeTernaryOperators: true
ColumnLimit: 0
AccessModifierOffset: -4
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: false
IndentCaseLabels: true
PointerAlignment: Left
ConstructorInitializerAllOnOneLineOrOnePerLine: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ fn main() {
.compile("notify");

println!("cargo:rerun-if-env-changed={}", DEPLOYMENT_TARGET_VAR);
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=objc");
}
}
50 changes: 38 additions & 12 deletions examples/actions.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
use mac_notification_sys::*;

fn main() {
let bundle = get_bundle_identifier_or_default("firefox");
set_application(&bundle).unwrap();
let response = send_notification(
"Danger",
Some("Will Robinson"),
"Run away as fast as you can",
"main button with drop down",
None,
"choose wisely",
Some(Notification::new().main_button(MainButton::DropdownActions(
"Dropdown",
&["Action 1", "Action 2"],
))),
)
.unwrap();
handle_repsonse(response);

let response = send_notification(
"take response",
None,
"type what you want",
Some(Notification::new().main_button(MainButton::Response(r#"you want "foobar""#))),
)
.unwrap();
handle_repsonse(response);

let response = send_notification(
"Single Action",
None,
"ok?",
Some(Notification::new().main_button(MainButton::SingleAction("Ok"))),
)
.unwrap();
handle_repsonse(response);

let response = send_notification(
"close button only",
None,
"close it well",
Some(
Notification::new()
.main_button(MainButton::DropdownActions(
"Dropdown",
&["Action 1", "Action 2"],
))
.close_button("Nevermind..."),
Notification::new().close_button("Nevermind..."),
),
)
.unwrap();
handle_repsonse(response);
}

match response {
fn handle_repsonse(response: NotificationResponse) {
match dbg!(response) {
// Requires main_button to be a MainButton::SingleAction or MainButton::DropdownActions
NotificationResponse::ActionButton(action_name) => {
if action_name == "Action 1" {
Expand Down
28 changes: 28 additions & 0 deletions examples/two_simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use mac_notification_sys::*;

fn main() {
let bundle = get_bundle_identifier_or_default("firefox");
println!("{}", bundle);

set_application(&bundle).unwrap();

Notification::default()
.title("Danger")
.subtitle("Will Robinson")
.message("Run away as fast as you can")
.send()
.unwrap();

Notification::default()
.title("two")
.message("two")
.send()
.unwrap();

Notification::default()
.title("NOW")
.message("Without subtitle")
.sound("Submarine")
.send()
.unwrap();
}
84 changes: 36 additions & 48 deletions objc/notify.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,81 @@
NSString* fakeBundleIdentifier = nil;

@implementation NSBundle (swizzle)
- (NSString*)__bundleIdentifier
{
if (self == [NSBundle mainBundle])
{
- (NSString*)__bundleIdentifier {
if (self == [NSBundle mainBundle]) {
return fakeBundleIdentifier ? fakeBundleIdentifier : @"com.apple.Terminal";
}
else
{
} else {
return [self __bundleIdentifier];
}
}
@end

BOOL installNSBundleHook()
{
BOOL installNSBundleHook() {
Class class = objc_getClass("NSBundle");
if (class)
{
if (class) {
method_exchangeImplementations(class_getInstanceMethod(class, @selector(bundleIdentifier)),
class_getInstanceMethod(class, @selector(__bundleIdentifier)));
return YES;
}
return NO;
}

@interface NotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate>
@interface NotificationCenterDelegate: NSObject <NSUserNotificationCenterDelegate>
@property(nonatomic, assign) BOOL keepRunning;
@property(nonatomic, retain) NSDictionary* actionData;
@end

// Delegate to respond to events in the NSUserNotificationCenter
// See https://developer.apple.com/documentation/foundation/nsusernotificationcenterdelegate?language=objc
@implementation NotificationCenterDelegate
- (void)userNotificationCenter:(NSUserNotificationCenter*)center didDeliverNotification:(NSUserNotification*)notification
{
- (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.keepRunning = NO;
}
}

// Most typical actions
- (void)userNotificationCenter:(NSUserNotificationCenter*)center didActivateNotification:(NSUserNotification*)notification
{
unsigned long long additionalActionIndex = ULLONG_MAX;
NSString* ActionsClicked = @"";
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification*)notification {
long long additionalActionIndex = ULONG_MAX;

// Switch on how the notification was interacted with
// See https://developer.apple.com/documentation/foundation/nsusernotification/1416143-activationtype?language=objc
switch (notification.activationType)
{
switch (notification.activationType) {
case NSUserNotificationActivationTypeActionButtonClicked:
case NSUserNotificationActivationTypeAdditionalActionClicked:
{
if ([[(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"] count] > 1)
{
case NSUserNotificationActivationTypeAdditionalActionClicked: {
if ([[(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"] count] > 1) {
NSNumber* alternateActionIndex = [(NSObject*)notification valueForKey:@"_alternateActionIndex"];
additionalActionIndex = [alternateActionIndex unsignedLongLongValue];
ActionsClicked = [(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"][additionalActionIndex];

self.actionData = @{@"activationType" : @"actionClicked", @"activationValue" : ActionsClicked, @"activationValueIndex" : [NSString stringWithFormat:@"%llu", additionalActionIndex]};
}
else
{
self.actionData = @{@"activationType" : @"actionClicked", @"activationValue" : notification.actionButtonTitle};
if (additionalActionIndex == LONG_MAX) {
self.actionData = @{@"activationType": @"actionClicked", @"activationValue": notification.actionButtonTitle};
break;
}

NSString* ActionsClicked = [(NSObject*)notification valueForKey:@"_alternateActionButtonTitles"][additionalActionIndex];

self.actionData = @{@"activationType": @"actionClicked", @"activationValue": ActionsClicked, @"activationValueIndex": [NSString stringWithFormat:@"%llu", additionalActionIndex]};
} else {
self.actionData = @{@"activationType": @"actionClicked", @"activationValue": notification.actionButtonTitle};
}
break;
}

case NSUserNotificationActivationTypeContentsClicked:
{
self.actionData = @{@"activationType" : @"contentsClicked"};
case NSUserNotificationActivationTypeContentsClicked: {
self.actionData = @{@"activationType": @"contentsClicked"};
break;
}

case NSUserNotificationActivationTypeReplied:
{
self.actionData = @{@"activationType" : @"replied", @"activationValue" : notification.response.string};
case NSUserNotificationActivationTypeReplied: {
self.actionData = @{@"activationType": @"replied", @"activationValue": notification.response.string};
break;
}
case NSUserNotificationActivationTypeNone:
default:
{
self.actionData = @{@"activationType" : @"none"};
default: {
self.actionData = @{@"activationType": @"none"};
break;
}
}
Expand All @@ -103,9 +93,9 @@ BOOL installNSBundleHook()
}

// Specific to the close/other button
- (void)userNotificationCenter:(NSUserNotificationCenter*)center didDismissAlert:(NSUserNotification*)notification
{
self.actionData = @{@"activationType" : @"closeClicked", @"activationValue" : notification.otherButtonTitle};
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDismissAlert:(NSUserNotification*)notification {
self.actionData = @{@"activationType": @"closeClicked", @"activationValue": notification.otherButtonTitle};

// Stop running after interacting with the notification
self.keepRunning = NO;
Expand All @@ -116,11 +106,9 @@ BOOL installNSBundleHook()
@end

// Utility function to create an NSImage from an url
NSImage* getImageFromURL(NSString* url)
{
NSImage* getImageFromURL(NSString* url) {
NSURL* imageURL = [NSURL URLWithString:url];
if ([[imageURL scheme] length] == 0)
{
if ([[imageURL scheme] length] == 0) {
// Prefix 'file://' if no scheme
imageURL = [NSURL fileURLWithPath:url];
}
Expand Down
Loading

0 comments on commit b5cc2b3

Please sign in to comment.