diff --git a/ios/RNFIRMessaging.m b/ios/RNFIRMessaging.m index f65947ffb88bece894673127d6f4666533a3ae71..b7de5e23b8b6b961654627d71b9278144ef9caad 100644 --- a/ios/RNFIRMessaging.m +++ b/ios/RNFIRMessaging.m @@ -140,7 +140,7 @@ typedef NS_ENUM(NSUInteger, UNNotificationActionType) { + (UNNotificationAction *) UNNotificationAction:(id)json { NSDictionary *details = [self NSDictionary:json]; - + NSString *identifier = [RCTConvert NSString: details[@"id"]]; NSString *title = [RCTConvert NSString: details[@"title"]]; UNNotificationActionOptions options = [RCTConvert UNNotificationActionOptions: details[@"options"]]; @@ -152,11 +152,11 @@ typedef NS_ENUM(NSUInteger, UNNotificationActionType) { return [UNTextInputNotificationAction actionWithIdentifier:identifier title:title options:options textInputButtonTitle:textInputButtonTitle textInputPlaceholder:textInputPlaceholder]; } - + return [UNNotificationAction actionWithIdentifier:identifier title:title options:options]; - + } RCT_ENUM_CONVERTER(UNNotificationActionType, (@{ @@ -180,9 +180,9 @@ RCT_MULTI_ENUM_CONVERTER(UNNotificationActionOptions, (@{ + (UNNotificationCategory *) UNNotificationCategory:(id)json { NSDictionary *details = [self NSDictionary:json]; - + NSString *identifier = [RCTConvert NSString: details[@"id"]]; - + NSMutableArray *actions = [[NSMutableArray alloc] init]; for (NSDictionary *actionDict in details[@"actions"]) { [actions addObject:[RCTConvert UNNotificationAction:actionDict]]; @@ -194,7 +194,7 @@ RCT_MULTI_ENUM_CONVERTER(UNNotificationActionOptions, (@{ if (hiddenPreviewsBodyPlaceholder) { #if defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 - return [UNNotificationCategory categoryWithIdentifier:identifier actions:actions intentIdentifiers:intentIdentifiers hiddenPreviewsBodyPlaceholder:hiddenPreviewsBodyPlaceholder options:options]; + return [UNNotificationCategory categoryWithIdentifier:identifier actions:actions intentIdentifiers:intentIdentifiers hiddenPreviewsBodyPlaceholder:hiddenPreviewsBodyPlaceholder options:options]; #endif } @@ -217,14 +217,15 @@ RCT_MULTI_ENUM_CONVERTER(UNNotificationCategoryOptions, (@{ @end -static NSDictionary *initialNotificationActionResponse; - @interface RNFIRMessaging () @property (nonatomic, strong) NSMutableDictionary *notificationCallbacks; @end @implementation RNFIRMessaging +static bool jsHandlerRegistered; +static NSMutableArray* pendingNotifications; + RCT_EXPORT_MODULE(); - (NSArray *)supportedEvents { @@ -239,14 +240,14 @@ RCT_EXPORT_MODULE(); NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo]; [data setValue:@"remote_notification" forKey:@"_notificationType"]; [data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"]; - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}]; + [self sendNotificationEventWhenAvailable:@{@"data": data, @"completionHandler": completionHandler}]; } + (void)didReceiveLocalNotification:(UILocalNotification *)notification { NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.userInfo]; [data setValue:@"local_notification" forKey:@"_notificationType"]; [data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"]; - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data}]; + [self sendNotificationEventWhenAvailable:@{@"data": data}]; } + (void)didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler @@ -261,24 +262,30 @@ RCT_EXPORT_MODULE(); if ([response isKindOfClass:UNTextInputNotificationResponse.class]) { [data setValue:[(UNTextInputNotificationResponse *)response userText] forKey:@"_userText"]; } - + NSDictionary *userInfo = @{@"data": data, @"completionHandler": completionHandler}; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - if (data[@"_actionIdentifier"] && ![data[@"_actionIdentifier"] isEqualToString:UNNotificationDefaultActionIdentifier]) { - initialNotificationActionResponse = userInfo; - } - }); - - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:userInfo]; + [self sendNotificationEventWhenAvailable:userInfo]; + } + (void)willPresentNotification:(UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler { NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.request.content.userInfo]; [data setValue:@"will_present_notification" forKey:@"_notificationType"]; - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}]; + [self sendNotificationEventWhenAvailable:@{@"data": data, @"completionHandler": completionHandler}]; +} + ++ (void)sendNotificationEventWhenAvailable:(NSDictionary*)data +{ + if(!jsHandlerRegistered){ + // JS hasn't registered callback yet. hold on that + if(!pendingNotifications){ + pendingNotifications = [NSMutableArray array]; + } + [pendingNotifications addObject:data]; + } else { + [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:data]; + } } - (void)dealloc @@ -288,10 +295,11 @@ RCT_EXPORT_MODULE(); - (instancetype)init { self = [super init]; + [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleNotificationReceived:) - name:FCMNotificationReceived - object:nil]; + selector:@selector(handleNotificationReceived:) + name:FCMNotificationReceived + object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sendDataMessageFailure:) @@ -309,17 +317,26 @@ RCT_EXPORT_MODULE(); dispatch_async(dispatch_get_main_queue(), ^{ [[FIRMessaging messaging] setDelegate:self]; }); + return self; } -(void) addListener:(NSString *)eventName { - if([super respondsToSelector:@selector(addListener:)]){ - [super addListener:eventName]; - } + [super addListener:eventName]; - if([eventName isEqualToString:FCMNotificationReceived] && initialNotificationActionResponse) { - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:[initialNotificationActionResponse copy]]; - } + if([eventName isEqualToString:FCMNotificationReceived]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + jsHandlerRegistered = true; + + for (NSDictionary* data in pendingNotifications) { + [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:data]; + } + + [pendingNotifications removeAllObjects]; + + }); + } } RCT_EXPORT_METHOD(enableDirectChannel) @@ -336,6 +353,7 @@ RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecte { NSDictionary* initialNotif; NSDictionary *localUserInfo = [[self.bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey] userInfo] mutableCopy]; + NSDictionary *remoteUserInfo = [self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] mutableCopy]; if(localUserInfo){ initialNotif = localUserInfo; @@ -346,10 +364,13 @@ RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecte [initialNotif setValue:@YES forKey:@"opened_from_tray"]; resolve(initialNotif); } else { - resolve(nil); + + resolve([self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityTypeKey] copy]); } } + + RCT_EXPORT_METHOD(getAPNSToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSData * deviceToken = [FIRMessaging messaging].APNSToken; @@ -366,47 +387,16 @@ RCT_EXPORT_METHOD(getFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromi resolve([FIRMessaging messaging].FCMToken); } -RCT_EXPORT_METHOD(getEntityFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -{ - FIROptions *options = FIROptions.defaultOptions; - NSString *entity = options.GCMSenderID; - NSData * deviceToken = [FIRMessaging messaging].APNSToken; - - [[FIRInstanceID instanceID]tokenWithAuthorizedEntity:entity scope:kFIRInstanceIDScopeFirebaseMessaging options:@{@"apns_token": deviceToken} handler:^(NSString * _Nullable token, NSError * _Nullable error) { - - if (error != nil) { - reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil); - } else { - resolve(token); - } - }]; -} - -RCT_EXPORT_METHOD(deleteEntityFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -{ - FIROptions *options = FIROptions.defaultOptions;; - NSString *entity = options.GCMSenderID; - - [[FIRInstanceID instanceID]deleteTokenWithAuthorizedEntity:entity scope:kFIRInstanceIDScopeFirebaseMessaging handler:^(NSError * _Nullable error) { - - if (error != nil) { - reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil); - } else { - resolve(nil); - } - }]; -} - RCT_EXPORT_METHOD(deleteInstanceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - [[FIRInstanceID instanceID]deleteIDWithHandler:^(NSError * _Nullable error) { - - if (error != nil) { - reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil); - } else { - resolve(nil); - } - }]; + [[FIRInstanceID instanceID]deleteIDWithHandler:^(NSError * _Nullable error) { + + if (error != nil) { + reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil); + } else { + resolve(nil); + } + }]; } - (void)messaging:(nonnull FIRMessaging *)messaging didRefreshRegistrationToken:(nonnull NSString *)fcmToken { @@ -655,12 +645,7 @@ RCT_EXPORT_METHOD(finishNotificationResponse: (NSString *)completionHandlerId){ self.notificationCallbacks[completionHandlerId] = completionHandler; data[@"_completionHandlerId"] = completionHandlerId; } - [self sendEventWithName:FCMNotificationReceived body:data]; - - if (initialNotificationActionResponse) { - initialNotificationActionResponse = nil; - } } - (void)sendDataMessageFailure:(NSNotification *)notification