From b8180c9b5116dc67df3bae5f5f79aa39f9de4cbb Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Thu, 2 Jun 2016 07:51:44 -0700 Subject: [PATCH 1/6] PushNotificationIOS requestPermission promisified --- .../PushNotificationIOS.js | 12 ++++- .../RCTPushNotificationManager.m | 45 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Libraries/PushNotificationIOS/PushNotificationIOS.js b/Libraries/PushNotificationIOS/PushNotificationIOS.js index 89b8dc986aa17b..0fd8260625412d 100644 --- a/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -216,12 +216,20 @@ class PushNotificationIOS { * * If a map is provided to the method, only the permissions with truthy values * will be requested. + + * This method returns a promise that will resolve when the user accepts, + * rejects, or if the permissions were previously rejected. The promise + * resolves to the current state of the permission. */ static requestPermissions(permissions?: { alert?: boolean, badge?: boolean, sound?: boolean - }) { + }): Promise<{ + alert: boolean, + badge: boolean, + sound: boolean + }> { var requestedPermissions = {}; if (permissions) { requestedPermissions = { @@ -236,7 +244,7 @@ class PushNotificationIOS { sound: true }; } - RCTPushNotificationManager.requestPermissions(requestedPermissions); + return RCTPushNotificationManager.requestPermissions(requestedPermissions); } /** diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 64f0e8de512680..101e3e8e7bd306 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -27,6 +27,13 @@ NSString *const RCTLocalNotificationReceived = @"LocalNotificationReceived"; NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived"; NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered"; +NSString *const RCTRegisterUserNotificationSettings = @"RegisterUserNotificationSettings"; + +NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS"; + +@interface RCTPushNotificationManager () +@property (nonatomic, copy) RCTPromiseResolveBlock requestPermissionsResolveBlock; +@end @implementation RCTConvert (UILocalNotification) @@ -66,6 +73,10 @@ - (void)startObserving selector:@selector(handleRemoteNotificationsRegistered:) name:RCTRemoteNotificationsRegistered object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleRegisterUserNotificationSettings:) + name:RCTRegisterUserNotificationSettings + object:nil]; } - (void)stopObserving @@ -93,6 +104,9 @@ + (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings { if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) { [[UIApplication sharedApplication] registerForRemoteNotifications]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTRegisterUserNotificationSettings + object:self + userInfo:notificationSettings]; } } @@ -145,6 +159,25 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification [self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo]; } +- (void)handleRegisterUserNotificationSettings:(NSNotification *)notification +{ + if (self.requestPermissionsResolveBlock == nil) return; + + NSMutableDictionary* notificationTypes = [NSMutableDictionary dictionaryWithObjectsAndKeys:@NO, @"alert", @NO, @"badge", @NO, @"sound", nil]; + UIUserNotificationSettings *notificationSettings = notification.userInfo; + if (notificationSettings.types & UIUserNotificationTypeAlert) { + notificationTypes[@"alert"] = @YES; + } + if (notificationSettings.types & UIUserNotificationTypeSound) { + notificationTypes[@"sound"] = @YES; + } + if (notificationSettings.types & UIUserNotificationTypeBadge) { + notificationTypes[@"badge"] = @YES; + } + self.requestPermissionsResolveBlock(notificationTypes); + self.requestPermissionsResolveBlock = nil; +} + /** * Update the application icon badge number on the home screen */ @@ -161,12 +194,22 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification callback(@[@(RCTSharedApplication().applicationIconBadgeNumber)]); } -RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions) +RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { if (RCTRunningInAppExtension()) { + reject(RCTErrorUnableToRequestPermissions, nil, RCTErrorWithMessage(@"Requesting push notifications is currently unavailable in an app extension")); return; } + if (self.requestPermissionsResolveBlock != nil) { + NSString *message = @"Cannot call requestPermissions twice before the first has returned."; + [NSException raise:RCTFatalExceptionName format:@"%@", message]; + } + + self.requestPermissionsResolveBlock = resolve; + UIUserNotificationType types = UIUserNotificationTypeNone; if (permissions) { if ([RCTConvert BOOL:permissions[@"alert"]]) { From 636517562a54fd7570d03cba836397057a4fb3c1 Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Fri, 3 Jun 2016 09:18:10 -0700 Subject: [PATCH 2/6] short hand to create notification types --- .../RCTPushNotificationManager.m | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 101e3e8e7bd306..02c59b0b3d23c2 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -161,19 +161,16 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification { - if (self.requestPermissionsResolveBlock == nil) return; - - NSMutableDictionary* notificationTypes = [NSMutableDictionary dictionaryWithObjectsAndKeys:@NO, @"alert", @NO, @"badge", @NO, @"sound", nil]; - UIUserNotificationSettings *notificationSettings = notification.userInfo; - if (notificationSettings.types & UIUserNotificationTypeAlert) { - notificationTypes[@"alert"] = @YES; - } - if (notificationSettings.types & UIUserNotificationTypeSound) { - notificationTypes[@"sound"] = @YES; - } - if (notificationSettings.types & UIUserNotificationTypeBadge) { - notificationTypes[@"badge"] = @YES; + if (self.requestPermissionsResolveBlock == nil) { + return; } + UIUserNotificationSettings *notificationSettings = notification.userInfo; + NSDictionary *notificationTypes = @{ + @"alert": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeAlert], + @"sound": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeSound], + @"badge": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeBadge], + }; + self.requestPermissionsResolveBlock(notificationTypes); self.requestPermissionsResolveBlock = nil; } From ef8c06626b814ce50ddd01a907d6d2de7e6fad39 Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Fri, 3 Jun 2016 09:18:24 -0700 Subject: [PATCH 3/6] dont throw, instead use RCTLogError --- Libraries/PushNotificationIOS/RCTPushNotificationManager.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 02c59b0b3d23c2..65e7cdbdb7ddc7 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -201,8 +201,8 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification } if (self.requestPermissionsResolveBlock != nil) { - NSString *message = @"Cannot call requestPermissions twice before the first has returned."; - [NSException raise:RCTFatalExceptionName format:@"%@", message]; + RCTLogError(@"Cannot call requestPermissions twice before the first has returned."); + return; } self.requestPermissionsResolveBlock = resolve; From 8344774fcf8d0608c4dffe1b620e22c23142fca7 Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Fri, 3 Jun 2016 09:46:23 -0700 Subject: [PATCH 4/6] short hand bool --- Libraries/PushNotificationIOS/RCTPushNotificationManager.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 65e7cdbdb7ddc7..e1a18fe799bfd4 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -166,9 +166,9 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification } UIUserNotificationSettings *notificationSettings = notification.userInfo; NSDictionary *notificationTypes = @{ - @"alert": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeAlert], - @"sound": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeSound], - @"badge": [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeBadge], + @"alert": @((BOOL)notificationSettings.types & UIUserNotificationTypeAlert), + @"sound": @((BOOL)notificationSettings.types & UIUserNotificationTypeSound), + @"badge": @((BOOL)notificationSettings.types & UIUserNotificationTypeBadge), }; self.requestPermissionsResolveBlock(notificationTypes); From afed56b06c1af1f850ff8c98ebc937648b466ef6 Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Fri, 3 Jun 2016 13:14:03 -0700 Subject: [PATCH 5/6] bitwise and then compare then cast to number --- Libraries/PushNotificationIOS/RCTPushNotificationManager.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index e1a18fe799bfd4..a7a00dd98dab99 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -166,9 +166,9 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification } UIUserNotificationSettings *notificationSettings = notification.userInfo; NSDictionary *notificationTypes = @{ - @"alert": @((BOOL)notificationSettings.types & UIUserNotificationTypeAlert), - @"sound": @((BOOL)notificationSettings.types & UIUserNotificationTypeSound), - @"badge": @((BOOL)notificationSettings.types & UIUserNotificationTypeBadge), + @"alert": @((notificationSettings.types & UIUserNotificationTypeAlert) > 0), + @"sound": @((notificationSettings.types & UIUserNotificationTypeSound) > 0), + @"badge": @((notificationSettings.types & UIUserNotificationTypeBadge) > 0), }; self.requestPermissionsResolveBlock(notificationTypes); From 45c9e152b3f6982315be3614b22c232cb8f5c237 Mon Sep 17 00:00:00 2001 From: Jonathan Stanton Date: Fri, 3 Jun 2016 15:01:59 -0700 Subject: [PATCH 6/6] userInfo is a dictionary, dont abuse the system --- Libraries/PushNotificationIOS/RCTPushNotificationManager.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index a7a00dd98dab99..329f7644d3f91a 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -106,7 +106,7 @@ + (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings [[UIApplication sharedApplication] registerForRemoteNotifications]; [[NSNotificationCenter defaultCenter] postNotificationName:RCTRegisterUserNotificationSettings object:self - userInfo:notificationSettings]; + userInfo:@{@"notificationSettings": notificationSettings}]; } } @@ -164,7 +164,8 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification if (self.requestPermissionsResolveBlock == nil) { return; } - UIUserNotificationSettings *notificationSettings = notification.userInfo; + + UIUserNotificationSettings *notificationSettings = notification.userInfo[@"notificationSettings"]; NSDictionary *notificationTypes = @{ @"alert": @((notificationSettings.types & UIUserNotificationTypeAlert) > 0), @"sound": @((notificationSettings.types & UIUserNotificationTypeSound) > 0),