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..329f7644d3f91a 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": notificationSettings}]; } } @@ -145,6 +159,23 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification [self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo]; } +- (void)handleRegisterUserNotificationSettings:(NSNotification *)notification +{ + if (self.requestPermissionsResolveBlock == nil) { + return; + } + + UIUserNotificationSettings *notificationSettings = notification.userInfo[@"notificationSettings"]; + NSDictionary *notificationTypes = @{ + @"alert": @((notificationSettings.types & UIUserNotificationTypeAlert) > 0), + @"sound": @((notificationSettings.types & UIUserNotificationTypeSound) > 0), + @"badge": @((notificationSettings.types & UIUserNotificationTypeBadge) > 0), + }; + + self.requestPermissionsResolveBlock(notificationTypes); + self.requestPermissionsResolveBlock = nil; +} + /** * Update the application icon badge number on the home screen */ @@ -161,12 +192,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) { + RCTLogError(@"Cannot call requestPermissions twice before the first has returned."); + return; + } + + self.requestPermissionsResolveBlock = resolve; + UIUserNotificationType types = UIUserNotificationTypeNone; if (permissions) { if ([RCTConvert BOOL:permissions[@"alert"]]) {