diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -58,6 +58,8 @@ CB4821AC27CFB17C001AB7E1 /* Session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B6F26B3FF0900EDE27D /* Session.cpp */; }; CB4821AE27CFB187001AB7E1 /* Tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B7326B401D300EDE27D /* Tools.cpp */; }; CB4821AF27CFB19D001AB7E1 /* PlatformSpecificTools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */; }; + CB7EF17E295C674300B17035 /* CommIOSNotifications.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */; }; + CB7EF180295C674300B17035 /* CommIOSNotificationsBridgeQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */; }; CB90951F29534B32002F2A7F /* CommSecureStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71D4D7CB26C50B1000FCDBCD /* CommSecureStore.mm */; }; CBDEC69B28ED867000C17588 /* GlobalDBSingleton.mm in Sources */ = {isa = PBXBuildFile; fileRef = CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */; }; CBFE58292885852B003B94C9 /* ThreadOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBFE58282885852B003B94C9 /* ThreadOperations.cpp */; }; @@ -205,6 +207,7 @@ CB3C621327CE66540054F24C /* libEXSecureStore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libEXSecureStore.a; sourceTree = BUILT_PRODUCTS_DIR; }; CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = CommIOSNotificationsBridgeQueue.mm; path = Comm/CommIOSNotifications/CommIOSNotificationsBridgeQueue.mm; sourceTree = ""; }; CB7EF17C295C580500B17035 /* CommIOSNotificationsBridgeQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommIOSNotificationsBridgeQueue.h; path = Comm/CommIOSNotifications/CommIOSNotificationsBridgeQueue.h; sourceTree = ""; }; + CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = CommIOSNotifications.mm; path = Comm/CommIOSNotifications/CommIOSNotifications.mm; sourceTree = ""; }; CB90951929531663002F2A7F /* CommIOSNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommIOSNotifications.h; path = Comm/CommIOSNotifications/CommIOSNotifications.h; sourceTree = ""; }; CBDEC69928ED859600C17588 /* GlobalDBSingleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalDBSingleton.h; sourceTree = ""; }; CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GlobalDBSingleton.mm; path = Comm/GlobalDBSingleton.mm; sourceTree = ""; }; @@ -555,6 +558,7 @@ CB90951729531647002F2A7F /* CommIOSNotifications */ = { isa = PBXGroup; children = ( + CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */, CB7EF17C295C580500B17035 /* CommIOSNotificationsBridgeQueue.h */, CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */, CB90951929531663002F2A7F /* CommIOSNotifications.h */, @@ -920,6 +924,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CB7EF17E295C674300B17035 /* CommIOSNotifications.mm in Sources */, + CB7EF180295C674300B17035 /* CommIOSNotificationsBridgeQueue.mm in Sources */, 7F0C6E31291C4468002AA2D9 /* ExpoModulesProvider.swift in Sources */, 75291F0428F9A0D400F4C80E /* DeviceID.cpp in Sources */, 8E43C32C291E5B4A009378F5 /* TerminateApp.mm in Sources */, diff --git a/native/ios/Comm/CommIOSNotifications/CommIOSNotifications.mm b/native/ios/Comm/CommIOSNotifications/CommIOSNotifications.mm new file mode 100644 --- /dev/null +++ b/native/ios/Comm/CommIOSNotifications/CommIOSNotifications.mm @@ -0,0 +1,179 @@ +#import "CommIOSNotifications.h" +#import "CommIOSNotificationsBridgeQueue.h" +#import +#import +#import +#import +#import + +/* + Internal Constants +*/ +NSString *const CommIOSNotificationsCreateAction = @"CREATE"; +NSString *const CommIOSNotificationsRegistered = + @"CommIOSNotificationsRegistered"; +NSString *const CommIOSNotificationsRegistrationFailed = + @"CommIOSNotificationsRegistrationFailed"; +NSString *const CommIOSNotificationsReceivedForeground = + @"CommIOSNotificationsReceivedForeground"; +NSString *const CommIOSNotificationsReceivedBackground = + @"CommIOSNotificationsReceivedBackground"; +NSString *const CommIOSNotificationsOpened = @"CommIOSNotificationsOpened"; +NSString *const CommIOSNotificationsActionTriggered = + @"CommIOSNotificationsActionTriggered"; + +@interface CommIOSNotifications () +@property(nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks; +@property(nonatomic) BOOL hasListeners; +@end + +@implementation CommIOSNotifications + +RCT_EXPORT_MODULE() + +@synthesize bridge = _bridge; + +- (void)setBridge:(RCTBridge *)bridge { + _bridge = bridge; + [CommIOSNotificationsBridgeQueue sharedInstance].openedRemoteNotification = + [_bridge.launchOptions + objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; + UILocalNotification *localNotification = [_bridge.launchOptions + objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; + [CommIOSNotificationsBridgeQueue sharedInstance].openedLocalNotification = + localNotification ? localNotification.userInfo : nil; +} + +- (void)stopObserving { + _hasListeners = NO; +} + +- (void)startObserving { + _hasListeners = YES; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return self; + } + _hasListeners = NO; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationsRegistered:) + name:CommIOSNotificationsRegistered + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationsRegistrationFailed:) + name:CommIOSNotificationsRegistrationFailed + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationReceivedForeground:) + name:CommIOSNotificationsReceivedForeground + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationReceivedBackground:) + name:CommIOSNotificationsReceivedBackground + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationOpened:) + name:CommIOSNotificationsOpened + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleNotificationActionTriggered:) + name:CommIOSNotificationsActionTriggered + object:nil]; + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (NSArray *)supportedEvents { + return @[ + @"remoteNotificationsRegistered", + @"remoteNotificationsRegistrationFailed", + @"notificationActionReceived", + @"notificationReceivedBackground", + @"notificationReceivedForeground", + @"notificationOpened" + ]; +} + +/* + JavaScript Events + */ +- (void)handleNotificationsRegistered:(NSNotification *)notification { + if (!_hasListeners) { + return; + } + [self sendEventWithName:@"remoteNotificationsRegistered" + body:notification.userInfo]; +} + +- (void)handleNotificationsRegistrationFailed:(NSNotification *)notification { + if (!_hasListeners) { + return; + } + [self sendEventWithName:@"remoteNotificationsRegistrationFailed" + body:notification.userInfo]; +} + +- (void)handleNotifInfo:(NSDictionary *)notifInfo withName:(NSString *)name { + NSDictionary *notification = notifInfo[@"notification"]; + NSString *notifID = notification[@"id"]; + RCTRemoteNotificationCallback completionHandler = + notifInfo[@"completionHandler"]; + if (completionHandler && notifID) { + if (!self.remoteNotificationCallbacks) { + // Lazy initialization + self.remoteNotificationCallbacks = [NSMutableDictionary dictionary]; + } + self.remoteNotificationCallbacks[notifID] = completionHandler; + } + [self sendEventWithName:name body:notification]; +} + +- (void)handleNotificationReceivedForeground:(NSNotification *)sysNotif { + if (!_hasListeners) { + return; + } + [self handleNotifInfo:sysNotif.userInfo + withName:@"notificationReceivedForeground"]; +} + +- (void)handleNotificationReceivedBackground:(NSNotification *)sysNotif { + if (!_hasListeners) { + return; + } + [self handleNotifInfo:sysNotif.userInfo + withName:@"notificationReceivedBackground"]; +} + +- (void)handleNotificationOpened:(NSNotification *)sysNotif { + if (!_hasListeners) { + return; + } + [self handleNotifInfo:sysNotif.userInfo withName:@"notificationOpened"]; +} + +- (void)handleNotificationActionTriggered:(NSNotification *)notification { + if (!_hasListeners) { + return; + } + [self sendEventWithName:@"notificationActionReceived" + body:notification.userInfo]; +} + +@end