PushNotificationIOS requestPermission promisified
Summary: **Motivation** Today it's hard to build a good flow around requesting permissions if we don't know when the user rejects the push notification permission. With this PR I wrap `PushNotificationIOS#requestPermission` in a promise. The promise will return with the updated permissions when the user accepts, rejects or has previously rejected the permission. An example flow of how an app should handle push notifications with the change proposed: 1) Show user an explanation of push notification permissions with a button to enable, 2) User presses the enable push notifications button, 3) If the user accepts -> take them into the app, 4) if the user rejects -> explain how to enable permission in the settings app. 5) My app will now store some state about how it has asked permissions for push notifications so that the next time the user is taken through this flow they will go straight to step 4. Without this change we could listen to the `register` event that PushNotificationIOS fires on the success sc Closes https://github.com/facebook/react-native/pull/7900 Differential Revision: D3387424 Pulled By: nicklockwood fbshipit-source-id: e27df41e83216e4e2a14d1e42c6b26e72236f48c
This commit is contained in:
parent
724134746b
commit
f4dbf37ba8
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 @@ RCT_EXPORT_MODULE()
|
|||
selector:@selector(handleRemoteNotificationsRegistered:)
|
||||
name:RCTRemoteNotificationsRegistered
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleRegisterUserNotificationSettings:)
|
||||
name:RCTRegisterUserNotificationSettings
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)stopObserving
|
||||
|
@ -93,6 +104,9 @@ RCT_EXPORT_MODULE()
|
|||
{
|
||||
if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) {
|
||||
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRegisterUserNotificationSettings
|
||||
object:self
|
||||
userInfo:@{@"notificationSettings": notificationSettings}];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +159,23 @@ RCT_EXPORT_MODULE()
|
|||
[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 @@ RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback
|
|||
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"]]) {
|
||||
|
|
Loading…
Reference in New Issue