diff --git a/ios/RNFIRMessaging.h b/ios/RNFIRMessaging.h index da82b385..c06f7662 100644 --- a/ios/RNFIRMessaging.h +++ b/ios/RNFIRMessaging.h @@ -1,9 +1,7 @@ #import -@import FirebaseAnalytics; @import FirebaseInstanceID; -@import FirebaseMessaging; #import "RCTBridgeModule.h" diff --git a/ios/RNFIRMesssaging.m b/ios/RNFIRMesssaging.m index c51a7723..10f3bae2 100644 --- a/ios/RNFIRMesssaging.m +++ b/ios/RNFIRMesssaging.m @@ -6,6 +6,7 @@ #import "RCTUtils.h" @import UserNotifications; +@import FirebaseMessaging; #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 @@ -21,28 +22,66 @@ @implementation RCTConvert (NSCalendarUnit) -+ (NSCalendarUnit *)NSCalendarUnit:(id)json +RCT_ENUM_CONVERTER(NSCalendarUnit, + (@{ + @"year": @(NSCalendarUnitYear), + @"month": @(NSCalendarUnitMonth), + @"week": @(NSCalendarUnitWeekOfYear), + @"day": @(NSCalendarUnitDay), + @"hour": @(NSCalendarUnitHour), + @"minute": @(NSCalendarUnitMinute) + }), + 0, + integerValue) +@end + + +@implementation RCTConvert (UNNotificationRequest) + ++ (UNNotificationRequest *)UNNotificationRequest:(id)json { - NSString* key = [self NSString:json]; - if([key isEqualToString:@"minute"]){ - return NSCalendarUnitMinute; - } - if([key isEqualToString:@"second"]){ - return NSCalendarUnitSecond; - } - if([key isEqualToString:@"day"]){ - return NSCalendarUnitDay; - } - if([key isEqualToString:@"month"]){ - return NSCalendarUnitMonth; - } - if([key isEqualToString:@"week"]){ - return NSCalendarUnitWeekOfYear; - } - if([key isEqualToString:@"year"]){ - return NSCalendarUnitYear; + NSDictionary *details = [self NSDictionary:json]; + UNMutableNotificationContent *content = [UNMutableNotificationContent new]; + content.title =[RCTConvert NSString:details[@"title"]]; + content.body =[RCTConvert NSString:details[@"body"]]; + content.sound = [RCTConvert NSString:details[@"sound"]] ?: [UNNotificationSound defaultSound]; + content.categoryIdentifier = [RCTConvert NSString:details[@"click_action"]]; + content.userInfo = details; + content.badge = [RCTConvert NSNumber:details[@"badge"]]; + + NSDate *fireDate = [RCTConvert NSDate:details[@"fire_date"]] ?: [NSDate date]; + NSCalendarUnit interval = [RCTConvert NSCalendarUnit:details[@"repeat_interval"]]; + NSCalendarUnit unitFlags; + switch (interval) { + case NSCalendarUnitMinute: { + unitFlags = NSCalendarUnitSecond; + break; + } + case NSCalendarUnitHour: { + unitFlags = NSCalendarUnitMinute | NSCalendarUnitSecond; + break; + } + case NSCalendarUnitDay: { + unitFlags = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + break; + } + case NSCalendarUnitWeekOfYear: { + unitFlags = NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + break; + } + case NSCalendarUnitMonth:{ + unitFlags = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + } + case NSCalendarUnitYear:{ + unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + } + default: + unitFlags = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + break; } - return 0; + NSDateComponents *components = [[NSCalendar currentCalendar] components:unitFlags fromDate:fireDate]; + UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:interval != 0]; + return [UNNotificationRequest requestWithIdentifier:[RCTConvert NSString:details[@"id"]] content:content trigger:trigger]; } @end @@ -54,7 +93,9 @@ + (UILocalNotification *)UILocalNotification:(id)json NSDictionary *details = [self NSDictionary:json]; UILocalNotification *notification = [UILocalNotification new]; notification.fireDate = [RCTConvert NSDate:details[@"fire_date"]] ?: [NSDate date]; - notification.alertTitle = [RCTConvert NSString:details[@"title"]]; + if([notification respondsToSelector:@selector(setAlertTitle:)]){ + [notification setAlertTitle:[RCTConvert NSString:details[@"title"]]]; + } notification.alertBody = [RCTConvert NSString:details[@"body"]]; notification.alertAction = [RCTConvert NSString:details[@"alert_action"]]; notification.soundName = [RCTConvert NSString:details[@"sound"]] ?: UILocalNotificationDefaultSoundName; @@ -64,7 +105,6 @@ + (UILocalNotification *)UILocalNotification:(id)json notification.applicationIconBadgeNumber = [RCTConvert NSInteger:details[@"badge"]]; return notification; } - @end @implementation RNFIRMessaging @@ -99,14 +139,14 @@ - (void)setBridge:(RCTBridge *)bridge [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTokenRefresh) name:kFIRInstanceIDTokenRefreshNotification object:nil]; - + [[NSNotificationCenter defaultCenter] - addObserver:self selector:@selector(sendDataMessageFailure:) - name:FIRMessagingSendErrorNotification object:nil]; - + addObserver:self selector:@selector(sendDataMessageFailure:) + name:FIRMessagingSendErrorNotification object:nil]; + [[NSNotificationCenter defaultCenter] - addObserver:self selector:@selector(sendDataMessageSuccess:) - name:FIRMessagingSendSuccessNotification object:nil]; + addObserver:self selector:@selector(sendDataMessageSuccess:) + name:FIRMessagingSendSuccessNotification object:nil]; // For iOS 10 data message (sent via FCM) [[FIRMessaging messaging] setRemoteMessageDelegate:self]; @@ -143,52 +183,6 @@ - (void)disconnectFCM resolve([[FIRInstanceID instanceID] token]); } -RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -{ - NSMutableArray* list = [[NSMutableArray alloc] init]; - for(UILocalNotification * notif in [RCTSharedApplication() scheduledLocalNotifications]){ - NSString* interval; - - switch(notif.repeatInterval){ - case NSCalendarUnitMinute: - interval = @"minute"; - break; - case NSCalendarUnitSecond: - interval = @"second"; - break; - case NSCalendarUnitDay: - interval = @"day"; - break; - case NSCalendarUnitMonth: - interval = @"month"; - break; - case NSCalendarUnitWeekOfYear: - interval = @"week"; - break; - case NSCalendarUnitYear: - interval = @"year"; - break; - } - NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary]; - if (notif.fireDate) { - NSDateFormatter *formatter = [NSDateFormatter new]; - [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"]; - NSString *fireDateString = [formatter stringFromDate:notif.fireDate]; - formattedLocalNotification[@"fire_date"] = fireDateString; - } - formattedLocalNotification[@"alert_action"] = RCTNullIfNil(notif.alertAction); - formattedLocalNotification[@"body"] = RCTNullIfNil(notif.alertBody); - formattedLocalNotification[@"title"] = RCTNullIfNil(notif.alertTitle); - formattedLocalNotification[@"badge"] = @(notif.applicationIconBadgeNumber); - formattedLocalNotification[@"click_action"] = RCTNullIfNil(notif.category); - formattedLocalNotification[@"sound"] = RCTNullIfNil(notif.soundName); - formattedLocalNotification[@"repeat_interval"] = RCTNullIfNil(interval); - formattedLocalNotification[@"data"] = RCTNullIfNil(RCTJSONClean(notif.userInfo)); - [list addObject:formattedLocalNotification]; - } - resolve(list); -} - - (void) onTokenRefresh { [_bridge.eventDispatcher sendDeviceEventWithName:@"FCMTokenRefreshed" body:[[FIRInstanceID instanceID] token]]; @@ -230,13 +224,6 @@ - (void) onTokenRefresh [[UIApplication sharedApplication] registerForRemoteNotifications]; } -#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 -// Receive data message on iOS 10 devices. -- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { - [_bridge.eventDispatcher sendDeviceEventWithName:FCMNotificationReceived body:[remoteMessage appData]]; -} -#endif - RCT_EXPORT_METHOD(subscribeToTopic: (NSString*) topic) { [[FIRMessaging messaging] subscribeToTopic:topic]; @@ -247,31 +234,92 @@ - (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMess [[FIRMessaging messaging] unsubscribeFromTopic:topic]; } -RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification) +// Receive data message on iOS 10 devices. +- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { + [_bridge.eventDispatcher sendDeviceEventWithName:FCMNotificationReceived body:[remoteMessage appData]]; +} + +RCT_EXPORT_METHOD(presentLocalNotification:(UNNotificationRequest *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - [RCTSharedApplication() presentLocalNotificationNow:notification]; + if([UNUserNotificationCenter currentNotificationCenter] != nil){ + UNNotificationRequest* request = [RCTConvert UNNotificationRequest:data]; + [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { + if (!error) { + resolve(nil); + }else{ + reject(@"notification_error", @"Failed to present local notificaton", error); + } + }]; + }else{ + UILocalNotification* notif = [RCTConvert UILocalNotification:data]; + [RCTSharedApplication() presentLocalNotificationNow:notif]; + resolve(nil); + } } -RCT_EXPORT_METHOD(scheduleLocalNotification:(UILocalNotification *)notification) +RCT_EXPORT_METHOD(scheduleLocalNotification:(id)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - [RCTSharedApplication() scheduleLocalNotification:notification]; + if([UNUserNotificationCenter currentNotificationCenter] != nil){ + UNNotificationRequest* request = [RCTConvert UNNotificationRequest:data]; + [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { + if (!error) { + resolve(nil); + }else{ + reject(@"notification_error", @"Failed to present local notificaton", error); + } + }]; + }else{ + UILocalNotification* notif = [RCTConvert UILocalNotification:data]; + [RCTSharedApplication() scheduleLocalNotification:notif]; + resolve(nil); + } } RCT_EXPORT_METHOD(cancelAllLocalNotifications) { - [RCTSharedApplication() cancelAllLocalNotifications]; + if([UNUserNotificationCenter currentNotificationCenter] != nil){ + [[UNUserNotificationCenter currentNotificationCenter] removeAllPendingNotificationRequests]; + [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications]; + } else { + [RCTSharedApplication() cancelAllLocalNotifications]; + } } RCT_EXPORT_METHOD(cancelLocalNotification:(NSString*) notificationId) { - for (UILocalNotification *notification in [UIApplication sharedApplication].scheduledLocalNotifications) { - NSDictionary *notificationInfo = notification.userInfo; - if([notificationId isEqualToString:[notificationInfo valueForKey:@"id"]]){ - [[UIApplication sharedApplication] cancelLocalNotification:notification]; + if([UNUserNotificationCenter currentNotificationCenter] != nil){ + [[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[notificationId]]; + }else { + for (UILocalNotification *notification in [UIApplication sharedApplication].scheduledLocalNotifications) { + NSDictionary *notificationInfo = notification.userInfo; + if([notificationId isEqualToString:[notificationInfo valueForKey:@"id"]]){ + [[UIApplication sharedApplication] cancelLocalNotification:notification]; + } } } } +RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + if([UNUserNotificationCenter currentNotificationCenter] != nil){ + [[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray * _Nonnull requests) { + NSMutableArray* list = [[NSMutableArray alloc] init]; + for(UNNotificationRequest * notif in requests){ + NSString* interval; + UNMutableNotificationContent *content = notif.content; + [list addObject:content.userInfo]; + } + resolve(list); + }]; + }else{ + NSMutableArray* list = [[NSMutableArray alloc] init]; + for(UILocalNotification * notif in [RCTSharedApplication() scheduledLocalNotifications]){ + [list addObject:notif.userInfo]; + } + resolve(list); + } +} + RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger*) number) { [RCTSharedApplication() setApplicationIconBadgeNumber:number]; @@ -289,15 +337,15 @@ - (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMess for (NSString* key in mMessage) { upstreamMessage[key] = [NSString stringWithFormat:@"%@", [mMessage valueForKey:key]]; } - + NSDictionary *imMessage = [NSDictionary dictionaryWithDictionary:upstreamMessage]; - + int64_t ttl = 3600; NSString * receiver = [NSString stringWithFormat:@"%@@gcm.googleapis.com", senderId]; - + NSUUID *uuid = [NSUUID UUID]; NSString * messageID = [uuid UUIDString]; - + [[FIRMessaging messaging]sendMessage:imMessage to:receiver withMessageID:messageID timeToLive:ttl]; } @@ -313,18 +361,18 @@ - (void)handleNotificationReceived:(NSNotification *)notification } -- (void)sendDataMessageFailure:(NSNotification *)notification +- (void)sendDataMessageFailure:(NSNotification *)notification { - NSString *messageID = (NSString *)notification.userInfo[@"messageID"]; - - NSLog(@"sendDataMessageFailure: %@", messageID); + NSString *messageID = (NSString *)notification.userInfo[@"messageID"]; + + NSLog(@"sendDataMessageFailure: %@", messageID); } -- (void)sendDataMessageSuccess:(NSNotification *)notification +- (void)sendDataMessageSuccess:(NSNotification *)notification { - NSString *messageID = (NSString *)notification.userInfo[@"messageID"]; - - NSLog(@"sendDataMessageSuccess: %@", messageID); + NSString *messageID = (NSString *)notification.userInfo[@"messageID"]; + + NSLog(@"sendDataMessageSuccess: %@", messageID); } @end