From c09641c107153942d1b965e709148f6a338f3395 Mon Sep 17 00:00:00 2001 From: Lidan Hifi Date: Thu, 14 Apr 2016 07:46:16 +0300 Subject: [PATCH] fix native interactive notifications support --- RNNotifications/RNNotifications.m | 140 ++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 47 deletions(-) diff --git a/RNNotifications/RNNotifications.m b/RNNotifications/RNNotifications.m index 67d24b5..5561228 100644 --- a/RNNotifications/RNNotifications.m +++ b/RNNotifications/RNNotifications.m @@ -6,15 +6,16 @@ #import "RCTConvert.h" #import "RCTUtils.h" -NSString *const RNNotificationCreateAction = @"CREATE"; -NSString *const RNNotificationClearAction = @"CLEAR"; +NSString* const RNNotificationCreateAction = @"CREATE"; +NSString* const RNNotificationClearAction = @"CLEAR"; -NSString *const RNNotificationReceivedForeground = @"RNNotificationReceivedForeground"; -NSString *const RNNotificationReceivedBackground = @"RNNotificationReceivedBackground"; -NSString *const RNNotificationOpened = @"RNNotificationOpened"; +NSString* const RNNotificationReceivedForeground = @"RNNotificationReceivedForeground"; +NSString* const RNNotificationReceivedBackground = @"RNNotificationReceivedBackground"; +NSString* const RNNotificationOpened = @"RNNotificationOpened"; +NSString* const RNNotificationActionTriggered = @"RNNotificationActionTriggered"; /* - * Enum Converters for Interactive Notifications + * Converters for Interactive Notifications */ @implementation RCTConvert (UIUserNotificationActivationMode) RCT_ENUM_CONVERTER(UIUserNotificationActivationMode, (@{ @@ -38,23 +39,48 @@ RCT_ENUM_CONVERTER(UIUserNotificationActionBehavior, (@{ }), UIUserNotificationActionBehaviorDefault, integerValue) @end -@implementation RNNotifications - -RCT_EXPORT_MODULE() +@implementation RCTConvert (UIMutableUserNotificationAction) ++ (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json +{ + NSDictionary *details = [self NSDictionary:json]; -@synthesize bridge = _bridge; + UIMutableUserNotificationAction* action =[[UIMutableUserNotificationAction alloc] init]; + action.activationMode = [RCTConvert UIUserNotificationActivationMode:details[@"activationMode"]]; + action.behavior = [RCTConvert UIUserNotificationActionBehavior:details[@"behavior"]]; + action.authenticationRequired = [RCTConvert BOOL:details[@"authenticationRequired"]]; + action.destructive = [RCTConvert BOOL:details[@"destructive"]]; + action.title = [RCTConvert NSString:details[@"title"]]; + action.identifier = [RCTConvert NSString:details[@"identifier"]]; -NSMutableDictionary *actionCallbacks; + return action; +} +@end -- (id)init +@implementation RCTConvert (UIMutableUserNotificationCategory) ++ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json { - if (self = [super init]) { - actionCallbacks = [[NSMutableDictionary alloc] init]; - return self; - } else { - return nil; + NSDictionary *details = [self NSDictionary:json]; + + UIMutableUserNotificationCategory* category = [[UIMutableUserNotificationCategory alloc] init]; + category.identifier = details[@"identifier"]; + + // category actions + NSMutableArray* actions = [[NSMutableArray alloc] init]; + for (NSDictionary* actionJson in [RCTConvert NSArray:details[@"actions"]]) { + [actions addObject:[RCTConvert UIMutableUserNotificationAction:actionJson]]; } + + [category setActions:actions forContext:[RCTConvert UIUserNotificationActionContext:details[@"context"]]]; + + return category; } +@end + +@implementation RNNotifications + +RCT_EXPORT_MODULE() + +@synthesize bridge = _bridge; - (void)dealloc { @@ -79,6 +105,11 @@ NSMutableDictionary *actionCallbacks; selector:@selector(handleNotificationOpened:) name:RNNotificationOpened object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleNotificationActionTriggered:) + name:RNNotificationActionTriggered + object:nil]; } /* @@ -113,6 +144,18 @@ NSMutableDictionary *actionCallbacks; } } ++ (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler +{ + [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:notification.userInfo]; + completionHandler(); +} + ++ (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler +{ + [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:userInfo]; + completionHandler(); +} + /* * Notification handlers */ @@ -157,7 +200,6 @@ NSMutableDictionary *actionCallbacks; /* * Helper methods */ - + (void)dispatchLocalNotificationFromNotification:(NSDictionary *)notification { NSDictionary* managedAps = [notification objectForKey:@"managedAps"]; @@ -211,48 +253,47 @@ NSMutableDictionary *actionCallbacks; return [NSString stringWithFormat:@"%@.%@", [[NSBundle mainBundle] bundleIdentifier], notificationId]; } -+ (UIMutableUserNotificationAction *)parseAction:(NSDictionary *)json -{ - UIMutableUserNotificationAction* action =[[UIMutableUserNotificationAction alloc] init]; - action.activationMode = [RCTConvert UIUserNotificationActivationMode:json[@"activationMode"]]; - action.behavior = [RCTConvert UIUserNotificationActionBehavior:json[@"behavior"]]; - action.authenticationRequired = [RCTConvert BOOL:json[@"authenticationRequired"]]; - action.destructive = [RCTConvert BOOL:json[@"destructive"]]; - action.title = json[@"title"]; - action.identifier = json[@"identifier"]; - - return action; -} - -+ (UIMutableUserNotificationCategory *)parseCategory:(NSDictionary *)json ++ (void)updateNotificationCategories:(NSArray *)json { - UIMutableUserNotificationCategory* category = [[UIMutableUserNotificationCategory alloc] init]; - category.identifier = json[@"identifier"]; + NSMutableSet* categories = nil; - // category actions - NSMutableArray* actions = [[NSMutableArray alloc] init]; - for (NSDictionary* actionJson in [RCTConvert NSArray:json[@"actions"]]) { - [actions addObject:[self parseAction:actionJson]]; + if ([json count] > 0) { + categories = [[NSMutableSet alloc] init]; + for (NSDictionary* categoryJson in json) { + [categories addObject:[RCTConvert UIMutableUserNotificationCategory:categoryJson]]; + } } - [category setActions:actions forContext:[RCTConvert UIUserNotificationActionContext:json[@"context"]]]; + UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert); + UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:types categories:categories]; - return category; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; } -+ (void)updateNotificationCategories:(NSArray *)json ++ (void)emitNotificationActionForIdentifier:(NSString *)identifier responseInfo:(NSDictionary *)responseInfo userInfo:(NSDictionary *)userInfo { - NSMutableSet* categories = [[NSMutableSet alloc] init]; - for (NSDictionary* categoryJson in json) { - [categories addObject:[self parseCategory:categoryJson]]; + NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier }]; + + // add text + NSString* text = [responseInfo objectForKey:UIUserNotificationActionResponseTypedTextKey]; + if (text != NULL) { + info[@"text"] = text; } - UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert); - UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:types categories:categories]; + // add notification custom data + if (userInfo != NULL) { + info[@"data"] = userInfo; + } - [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + // Emit event + [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered + object:self + userInfo:info]; } +/* + * Javascript events + */ - (void)handleNotificationReceivedForeground:(NSNotification *)notification { [_bridge.eventDispatcher sendDeviceEventWithName:@"notificationReceivedForeground" body:notification.userInfo]; @@ -268,6 +309,11 @@ NSMutableDictionary *actionCallbacks; [_bridge.eventDispatcher sendDeviceEventWithName:@"notificationOpened" body:notification.userInfo]; } +- (void)handleNotificationActionTriggered:(NSNotification *)notification +{ + [_bridge.eventDispatcher sendAppEventWithName:@"notificationActionReceived" body:notification.userInfo]; +} + /* * React Native exported methods */ -- 2.26.2