Skip to content
Permalink
Browse files

Correctly passes localNotification to app on wakeup

Summary:
Currently if an RN app is started in response to a remote notification, that notification's data is available on startup via `PushNotificationIOS.popInitialNotification()`. However, if the app is started in response to a "local" notification, that information is never passed in. This PR modifies the `popInitialNotification` behavior so it will return the notification used to launch the app, no matter if it was local or remote.

I've tested this change in my app and ensured that when the app is woken up with a `localNotification` it's passed in to `PushNotificationIOS.popInitialNotification`. I've also tested that the `localNotification` event continues working as before.
Closes #7765

Differential Revision: D3417267

Pulled By: nicklockwood

fbshipit-source-id: 0b5b432e9a75dda7d3c50289a3bf0f1c1ffcf061
  • Loading branch information...
corbt authored and Facebook Github Bot 8 committed Jun 10, 2016
1 parent 6236a59 commit 57d45235ecb5fc54c0b80d1147a38e712dd9c431
Showing with 48 additions and 27 deletions.
  1. +48 −27 Libraries/PushNotificationIOS/RCTPushNotificationManager.m
@@ -31,10 +31,6 @@

NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";

@interface RCTPushNotificationManager ()
@property (nonatomic, copy) RCTPromiseResolveBlock requestPermissionsResolveBlock;
@end

@implementation RCTConvert (UILocalNotification)

+ (UILocalNotification *)UILocalNotification:(id)json
@@ -56,12 +52,15 @@ + (UILocalNotification *)UILocalNotification:(id)json
@end

@implementation RCTPushNotificationManager
{
RCTPromiseResolveBlock _requestPermissionsResolveBlock;
}

static NSDictionary *formatLocalNotification(UILocalNotification *notification)
static NSDictionary *RCTFormatLocalNotification(UILocalNotification *notification)
{
NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary];
if (notification.fireDate) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"];
NSString *fireDateString = [formatter stringFromDate:notification.fireDate];
formattedLocalNotification[@"fireDate"] = fireDateString;
@@ -77,6 +76,11 @@ @implementation RCTPushNotificationManager

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}

- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
@@ -114,8 +118,18 @@ - (void)stopObserving
- (NSDictionary<NSString *, id> *)constantsToExport
{
NSDictionary<NSString *, id> *initialNotification =
[self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
return @{@"initialNotification": RCTNullIfNil(initialNotification)};
self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];

UILocalNotification *initialLocalNotification =
self.bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];

if (initialNotification) {
return @{@"initialNotification": [initialNotification copy]};
} else if (initialLocalNotification) {
return @{@"initialNotification": RCTFormatLocalNotification(initialLocalNotification)};
} else {
return @{@"initialNotification": (id)kCFNull};
}
}

+ (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
@@ -150,16 +164,9 @@ + (void)didReceiveRemoteNotification:(NSDictionary *)notification

+ (void)didReceiveLocalNotification:(UILocalNotification *)notification
{
NSMutableDictionary *details = [NSMutableDictionary new];
if (notification.alertBody) {
details[@"alertBody"] = notification.alertBody;
}
if (notification.userInfo) {
details[@"userInfo"] = RCTJSONClean(notification.userInfo);
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTLocalNotificationReceived
object:self
userInfo:details];
userInfo:RCTFormatLocalNotification(notification)];
}

- (void)handleLocalNotificationReceived:(NSNotification *)notification
@@ -179,7 +186,7 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification

- (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
{
if (self.requestPermissionsResolveBlock == nil) {
if (_requestPermissionsResolveBlock == nil) {
return;
}

@@ -190,8 +197,8 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
@"badge": @((notificationSettings.types & UIUserNotificationTypeBadge) > 0),
};

self.requestPermissionsResolveBlock(notificationTypes);
self.requestPermissionsResolveBlock = nil;
_requestPermissionsResolveBlock(notificationTypes);
_requestPermissionsResolveBlock = nil;
}

/**
@@ -219,12 +226,12 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
return;
}

if (self.requestPermissionsResolveBlock != nil) {
if (_requestPermissionsResolveBlock != nil) {
RCTLogError(@"Cannot call requestPermissions twice before the first has returned.");
return;
}

self.requestPermissionsResolveBlock = resolve;
_requestPermissionsResolveBlock = resolve;

UIUserNotificationType types = UIUserNotificationTypeNone;
if (permissions) {
@@ -298,11 +305,15 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
[RCTSharedApplication() cancelAllLocalNotifications];
}

RCT_EXPORT_METHOD(cancelLocalNotifications:(NSDictionary *)userInfo)
RCT_EXPORT_METHOD(cancelLocalNotifications:(NSDictionary<NSString *, id> *)userInfo)
{
for (UILocalNotification *notification in [UIApplication sharedApplication].scheduledLocalNotifications) {
__block BOOL matchesAll = YES;
NSDictionary *notificationInfo = notification.userInfo;
NSDictionary<NSString *, id> *notificationInfo = notification.userInfo;
// Note: we do this with a loop instead of just `isEqualToDictionary:`
// because we only require that all specified userInfo values match the
// notificationInfo values - notificationInfo may contain additional values
// which we don't care about.
[userInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
if (![notificationInfo[key] isEqual:obj]) {
matchesAll = NO;
@@ -319,16 +330,26 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
reject:(__unused RCTPromiseRejectBlock)reject)
{
NSDictionary<NSString *, id> *initialNotification =
[self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
resolve(RCTNullIfNil(initialNotification));
self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];

UILocalNotification *initialLocalNotification =
self.bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];

if (initialNotification) {
resolve([initialNotification copy]);
} else if (initialLocalNotification) {
resolve(RCTFormatLocalNotification(initialLocalNotification));
} else {
resolve((id)kCFNull);
}
}

RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTResponseSenderBlock)callback)
{
NSArray<UILocalNotification *> *scheduledLocalNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
NSMutableArray *formattedScheduledLocalNotifications = [[NSMutableArray alloc] init];
NSMutableArray<NSDictionary *> *formattedScheduledLocalNotifications = [NSMutableArray new];
for (UILocalNotification *notification in scheduledLocalNotifications) {
[formattedScheduledLocalNotifications addObject:formatLocalNotification(notification)];
[formattedScheduledLocalNotifications addObject:RCTFormatLocalNotification(notification)];
}
callback(@[formattedScheduledLocalNotifications]);
}

0 comments on commit 57d4523

Please sign in to comment.
You can’t perform that action at this time.