diff --git a/RNNotifications/RCTConvert+Notifications.h b/RNNotifications/RCTConvert+Notifications.h index eda4252923b107ff90a50d8094c259e6186d9d5c..aaff9dc987ecf9e008d4fdc244a1319969ae7f7c 100644 --- a/RNNotifications/RCTConvert+Notifications.h +++ b/RNNotifications/RCTConvert+Notifications.h @@ -42,8 +42,8 @@ static NSDictionary *RCTFormatUNNotification(UNNotification *notification) + (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json; @end -@interface RCTConvert (UIMutableUserNotificationCategory) -+ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json; +@interface RCTConvert (UNMutableUserNotificationCategory) ++ (UNNotificationCategory *)UNMutableUserNotificationCategory:(id)json; @end @interface RCTConvert (UILocalNotification) diff --git a/RNNotifications/RCTConvert+Notifications.m b/RNNotifications/RCTConvert+Notifications.m index 08986329dc8a5135da69f70d9175cd213269d6a6..2a330e1669d77a0f9d30e562a449e5011320eb19 100644 --- a/RNNotifications/RCTConvert+Notifications.m +++ b/RNNotifications/RCTConvert+Notifications.m @@ -10,53 +10,55 @@ RCT_ENUM_CONVERTER(UIUserNotificationActivationMode, (@{ }), UIUserNotificationActivationModeForeground, integerValue) @end -@implementation RCTConvert (UIUserNotificationActionContext) -RCT_ENUM_CONVERTER(UIUserNotificationActionContext, (@{ - @"default": @(UIUserNotificationActionContextDefault), - @"minimal": @(UIUserNotificationActionContextMinimal) - }), UIUserNotificationActionContextDefault, integerValue) -@end +//@implementation RCTConvert (UIUserNotificationActionContext) +//RCT_ENUM_CONVERTER(UIUserNotificationActionContext, (@{ +// @"default": @(UIUserNotificationActionContextDefault), +// @"minimal": @(UIUserNotificationActionContextMinimal) +// }), UIUserNotificationActionContextDefault, integerValue) +//@end + +@implementation RCTConvert (UNNotificationActionOptions) + ++ (UNNotificationActionOptions)UNUserNotificationActionOptions:(id)json { + UNNotificationActionOptions options = UNNotificationActionOptionNone; + if ([json[@"activationMode"] isEqualToString:@"foreground"]) { + options = options | UNNotificationActionOptionForeground; + } + if ([RCTConvert BOOL:json[@"authenticationRequired"]]) { + options = options | UNNotificationActionOptionAuthenticationRequired; + } + if ([RCTConvert BOOL:json[@"destructive"]]) { + options = options | UNNotificationActionOptionDestructive; + } + + return options; +} -@implementation RCTConvert (UIUserNotificationActionBehavior) -/* iOS 9 only */ -RCT_ENUM_CONVERTER(UIUserNotificationActionBehavior, (@{ - @"default": @(UIUserNotificationActionBehaviorDefault), - @"textInput": @(UIUserNotificationActionBehaviorTextInput) - }), UIUserNotificationActionBehaviorDefault, integerValue) @end -@implementation RCTConvert (UIMutableUserNotificationAction) -+ (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json +@implementation RCTConvert (UNMutableUserNotificationAction) ++ (UNNotificationAction *)UNMutableUserNotificationAction:(id)json { NSDictionary *details = [self NSDictionary:json]; - UIMutableUserNotificationAction* action =[UIMutableUserNotificationAction new]; - action.activationMode = [RCTConvert UIUserNotificationActivationMode:details[@"activationMode"]]; - action.behavior = [RCTConvert UIUserNotificationActionBehavior:details[@"behavior"]]; - action.authenticationRequired = [RCTConvert BOOL:details[@"authenticationRequired"]]; - action.destructive = [RCTConvert BOOL:details[@"destructive"]]; - action.title = [RCTConvert NSString:details[@"title"]]; - action.identifier = [RCTConvert NSString:details[@"identifier"]]; + UNNotificationAction* action = [UNNotificationAction actionWithIdentifier:details[@"identifier"] title:details[@"title"] options:[RCTConvert UNUserNotificationActionOptions:details]]; +// action.behavior = [RCTConvert UIUserNotificationActionBehavior:details[@"behavior"]]; return action; } @end -@implementation RCTConvert (UIMutableUserNotificationCategory) -+ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json +@implementation RCTConvert (UNMutableUserNotificationCategory) ++ (UNNotificationCategory *)UNMutableUserNotificationCategory:(id)json { NSDictionary *details = [self NSDictionary:json]; - UIMutableUserNotificationCategory* category = [UIMutableUserNotificationCategory new]; - category.identifier = details[@"identifier"]; - - // category actions NSMutableArray* actions = [NSMutableArray new]; for (NSDictionary* actionJson in [RCTConvert NSArray:details[@"actions"]]) { - [actions addObject:[RCTConvert UIMutableUserNotificationAction:actionJson]]; + [actions addObject:[RCTConvert UNMutableUserNotificationAction:actionJson]]; } - [category setActions:actions forContext:[RCTConvert UIUserNotificationActionContext:details[@"context"]]]; + UNNotificationCategory* category = [UNNotificationCategory categoryWithIdentifier:details[@"identifier"] actions:actions intentIdentifiers:@[] options:UNNotificationCategoryOptionNone]; return category; } diff --git a/RNNotifications/RNBridgeModule.m b/RNNotifications/RNBridgeModule.m index 81bde293c54141a2e9f6a4ca7664ceb2a8cd8f00..918843442d910ef052aa3d397323b3a82b918524 100644 --- a/RNNotifications/RNBridgeModule.m +++ b/RNNotifications/RNBridgeModule.m @@ -27,6 +27,11 @@ RCT_EXPORT_MODULE(); return YES; } +- (void)setBridge:(RCTBridge *)bridge { + _bridge = bridge; + [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; +} + #pragma mark - JS interface RCT_EXPORT_METHOD(requestPermissionsWithCategories:(NSArray *)json) { diff --git a/RNNotifications/RNCommandsHandler.m b/RNNotifications/RNCommandsHandler.m index 3d85aeade73580913887ce18800fbcb871c55a2c..848cf6132ff389723e5286e0b172a3237fb9393d 100644 --- a/RNNotifications/RNCommandsHandler.m +++ b/RNNotifications/RNCommandsHandler.m @@ -2,8 +2,11 @@ #import "RNNotifications.h" #import "RNNotificationsBridgeQueue.h" #import "RCTConvert+Notifications.h" +#import "RNPushKit.h" -@implementation RNCommandsHandler +@implementation RNCommandsHandler { + RNPushKit* _pushKit; +} - (instancetype)init { self = [super init]; @@ -15,30 +18,39 @@ } - (void)onJavaScriptLoaded { - [RNNotificationsBridgeQueue sharedInstance].jsIsReady = YES; +// [RNNotificationsBridgeQueue sharedInstance].jsIsReady = YES; } - (void)requestPermissionsWithCategories:(NSArray *)json { - NSMutableSet* categories = nil; + NSMutableSet* categories = nil; if ([json count] > 0) { categories = [NSMutableSet new]; for (NSDictionary* categoryJson in json) { - [categories addObject:[RCTConvert UIMutableUserNotificationCategory:categoryJson]]; + [categories addObject:[RCTConvert UNMutableUserNotificationCategory:categoryJson]]; } } - - [[RNNotifications sharedInstance] requestPermissionsWithCategories:categories]; + [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories]; + UNAuthorizationOptions authOptions = (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert); + [UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { + if (error) { + + } else { + if (granted) { + [UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { + if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) { + [[UIApplication sharedApplication] registerForRemoteNotifications]; + } + }]; + } else { + + } + } + }]; } - (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - NSDictionary * notification = nil; - notification = [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification ? - [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification : - [RNNotificationsBridgeQueue sharedInstance].openedLocalNotification; - [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = nil; - [RNNotificationsBridgeQueue sharedInstance].openedLocalNotification = nil; - resolve(notification); + resolve([RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification); } - (void)completionHandler:(NSString *)completionKey { @@ -50,7 +62,7 @@ } - (void)registerPushKit { - [[RNNotifications sharedInstance] registerPushKit]; + _pushKit = [[RNPushKit alloc] initWithPushKitEventListener:[RNPushKitEventListener new]]; } - (void)getBadgesCount:(RCTResponseSenderBlock)callback { diff --git a/RNNotifications/RNNotificationCenterListener.h b/RNNotifications/RNNotificationCenterListener.h new file mode 100644 index 0000000000000000000000000000000000000000..77a67dd3bb1983004939b5e155fb85f62de0ce9a --- /dev/null +++ b/RNNotifications/RNNotificationCenterListener.h @@ -0,0 +1,9 @@ +#import +@import UserNotifications; +#import "RNNotificationEventHandler.h" + +@interface RNNotificationCenterListener : NSObject + +- (instancetype)initWithNotificationEventHandler:(RNNotificationEventHandler *)notificationEventHandler; + +@end diff --git a/RNNotifications/RNNotificationCenterListener.m b/RNNotifications/RNNotificationCenterListener.m new file mode 100644 index 0000000000000000000000000000000000000000..487c8733ab17014a74af4bfd468ee3cb40e169ca --- /dev/null +++ b/RNNotifications/RNNotificationCenterListener.m @@ -0,0 +1,30 @@ +#import "RNNotificationCenterListener.h" + +@implementation RNNotificationCenterListener { + RNNotificationEventHandler* _notificationEventHandler; +} + +- (instancetype)initWithNotificationEventHandler:(RNNotificationEventHandler *)notificationEventHandler { + self = [super init]; + _notificationEventHandler = notificationEventHandler; + [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self]; + + return self; +} + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { + [_notificationEventHandler didReceiveForegroundPayload:notification.request.content.userInfo]; +} + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { + if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) { + [_notificationEventHandler didOpenNotificationPayload:response.notification.request.content.userInfo]; + } else if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) { + + } else { + NSString* responseText = [response isKindOfClass:[UNTextInputNotificationResponse class]] ? ((UNTextInputNotificationResponse *)response).userText : nil; + [_notificationEventHandler handleActionWithIdentifier:response.actionIdentifier forPayload:response.notification.request.content.userInfo withResponse:responseText completionHandler:completionHandler]; + } +} + +@end diff --git a/RNNotifications/RNNotificationEventHandler.h b/RNNotifications/RNNotificationEventHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..f43d52720eea67fb74fa79c3f068a1ba997717c5 --- /dev/null +++ b/RNNotifications/RNNotificationEventHandler.h @@ -0,0 +1,10 @@ +#import +@import UserNotifications; + +@interface RNNotificationEventHandler : NSObject + +- (void)didReceiveForegroundPayload:(NSDictionary *)payload; +- (void)didOpenNotificationPayload:(NSDictionary *)payload; +- (void)handleActionWithIdentifier:(NSString *)identifier forPayload:(NSDictionary *)payload withResponse:(NSString *)response completionHandler:(void (^)())completionHandler; + +@end diff --git a/RNNotifications/RNNotificationEventHandler.m b/RNNotifications/RNNotificationEventHandler.m new file mode 100644 index 0000000000000000000000000000000000000000..077121718580b2fbedf902d24b2f4aa9b74c91db --- /dev/null +++ b/RNNotifications/RNNotificationEventHandler.m @@ -0,0 +1,44 @@ +#import "RNNotificationEventHandler.h" +#import "RNNotificationsBridgeQueue.h" +#import "RNEventEmitter.h" + +@implementation RNNotificationEventHandler + +- (void)didReceiveForegroundPayload:(NSDictionary *)payload { +// if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) { + [RNEventEmitter sendEvent:NotificationReceivedForeground body:payload]; +// } +} + +- (void)didOpenNotificationPayload:(NSDictionary *)payload { +// if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) { + [RNEventEmitter sendEvent:NotificationOpened body:payload]; +// } +} + +- (void)handleActionWithIdentifier:(NSString *)identifier forPayload:(NSDictionary *)payload withResponse:(NSString *)response completionHandler:(void (^)())completionHandler { + [self emitNotificationActionForIdentifier:identifier response:response userInfo:payload completionHandler:completionHandler]; +} + +- (void)emitNotificationActionForIdentifier:(NSString *)identifier response:(NSString *)response userInfo:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { + NSString* completionKey = [NSString stringWithFormat:@"%@.%@", identifier, [NSString stringWithFormat:@"%ldd", (long)[[NSDate date] timeIntervalSince1970]]]; + NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier, @"completionKey": completionKey }]; + + if (response != NULL) { + info[@"text"] = response; + } + + // add notification custom data + if (userInfo != NULL) { + info[@"notification"] = userInfo; + } + + // Emit event to the queue (in order to store the completion handler). if JS thread is ready, post it also to the notification center (to the bridge). + [[RNNotificationsBridgeQueue sharedInstance] postAction:info withCompletionKey:completionKey andCompletionHandler:completionHandler]; + + // if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) { + [RNEventEmitter sendEvent:NotificationActionReceived body:userInfo]; + // } +} + +@end diff --git a/RNNotifications/RNNotifications.h b/RNNotifications/RNNotifications.h index 4f2ee77a8fc91527673e118398dcd7826c6b2a8d..88db4973e51b9fdb6cc1356818b171ad48376581 100644 --- a/RNNotifications/RNNotifications.h +++ b/RNNotifications/RNNotifications.h @@ -1,27 +1,15 @@ @import UIKit; - -#import #import @import UserNotifications; -@interface RNNotifications : NSObject +@interface RNNotifications : NSObject + (instancetype)sharedInstance; -- (void)requestPermissionsWithCategories:(NSMutableSet *)categories; -- (void)registerPushKit; - +- (void)initialize; - (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken; - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; -- (void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type; - -//- (void)didReceiveRemoteNotification:(NSDictionary *)notification; - -- (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler; -- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler; -- (void)didReceiveForegroundNotification:(UNNotification *)notification; -- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response; //- (void)setBadgeForNotification:(NSDictionary *)notification; @end diff --git a/RNNotifications/RNNotifications.m b/RNNotifications/RNNotifications.m index cf69bc865dcd8093877e437f7209a95006406a45..f4c64ff1a16207d065ca8883fa08c8c853d4f528 100644 --- a/RNNotifications/RNNotifications.m +++ b/RNNotifications/RNNotifications.m @@ -9,15 +9,15 @@ #import "RNNotificationsBridgeQueue.h" #import #import "RNEventEmitter.h" +#import "RNNotificationEventHandler.h" +#import "RNUtils.h" NSString* const RNNotificationCreateAction = @"CREATE"; NSString* const RNNotificationClearAction = @"CLEAR"; -@implementation RNNotifications - -RCT_EXPORT_MODULE() - -@synthesize bridge = _bridge; +@implementation RNNotifications { + RNNotificationEventHandler* _notificationEventHandler; +} + (instancetype)sharedInstance { static RNNotifications *sharedInstance = nil; @@ -29,29 +29,12 @@ RCT_EXPORT_MODULE() return sharedInstance; } -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -+ (BOOL)requiresMainQueueSetup { - return YES; +- (void)initialize { + _notificationEventHandler = [RNNotificationEventHandler new]; } -- (void)setBridge:(RCTBridge *)bridge -{ - _bridge = bridge; - [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; - UILocalNotification *localNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; - [RNNotificationsBridgeQueue sharedInstance].openedLocalNotification = localNotification ? localNotification.userInfo : nil; -} - -/* - * Public Methods - */ - - (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken { - NSString *tokenRepresentation = [deviceToken isKindOfClass:[NSString class]] ? deviceToken : [self deviceTokenToString:deviceToken]; + NSString *tokenRepresentation = [deviceToken isKindOfClass:[NSString class]] ? deviceToken : [RNUtils deviceTokenToString:deviceToken]; [RNEventEmitter sendEvent:Registered body:@{@"deviceToken": tokenRepresentation}]; } @@ -59,187 +42,10 @@ RCT_EXPORT_MODULE() [RNEventEmitter sendEvent:RegistrationFailed body:@{@"code": [NSNumber numberWithInteger:error.code], @"domain": error.domain, @"localizedDescription": error.localizedDescription}]; } -- (void)didReceiveForegroundNotification:(UNNotification *)notification { - if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) { - [self didReceiveNotificationOnForegroundState:notification]; - } -} - -- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response { - if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES && [response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) { - [self didNotificationOpen:response.notification.request.content.userInfo]; - } -} - -- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler -{ - [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:notification.userInfo completionHandler:completionHandler]; -} - -- (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler -{ - [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:userInfo completionHandler:completionHandler]; -} - - (void)setBadgeForNotification:(NSDictionary *)notification { if ([[notification objectForKey:@"aps"] objectForKey:@"badge"]){ [[UIApplication sharedApplication] setApplicationIconBadgeNumber:[[[notification objectForKey:@"aps"] objectForKey:@"badge"] intValue]]; } } -/* - * Notification handlers - */ -- (void)didReceiveNotificationOnForegroundState:(UNNotification *)notification { - [RNEventEmitter sendEvent:NotificationReceivedForeground body:notification.request.content.userInfo]; -} - -- (void)didReceiveNotificationOnBackgroundState:(NSDictionary *)notification { - NSDictionary* managedAps = [notification objectForKey:@"managedAps"]; - NSDictionary* alert = [managedAps objectForKey:@"alert"]; - NSString* action = [managedAps objectForKey:@"action"]; - NSString* notificationId = [managedAps objectForKey:@"notificationId"]; - - if (action) { - // create or delete notification - if ([action isEqualToString: RNNotificationCreateAction] - && notificationId - && alert) { - [self dispatchLocalNotificationFromNotification:notification]; - - } else if ([action isEqualToString: RNNotificationClearAction] && notificationId) { - [self clearNotificationFromNotificationsCenter:notificationId]; - } - } - - [RNEventEmitter sendEvent:NotificationReceivedBackground body:notification]; -} - -- (void)didNotificationOpen:(NSDictionary *)notification { - [RNEventEmitter sendEvent:NotificationOpened body:notification]; -} - -/* - * Helper methods - */ -- (void)dispatchLocalNotificationFromNotification:(NSDictionary *)notification { - NSDictionary* managedAps = [notification objectForKey:@"managedAps"]; - NSDictionary* alert = [managedAps objectForKey:@"alert"]; - NSString* action = [managedAps objectForKey:@"action"]; - NSString* notificationId = [managedAps objectForKey:@"notificationId"]; - - if ([action isEqualToString: RNNotificationCreateAction] - && notificationId - && alert) { - - // trigger new client push notification - UILocalNotification* note = [UILocalNotification new]; - note.alertTitle = [alert objectForKey:@"title"]; - note.alertBody = [alert objectForKey:@"body"]; - note.userInfo = notification; - note.soundName = [managedAps objectForKey:@"sound"]; - note.category = [managedAps objectForKey:@"category"]; - - [[UIApplication sharedApplication] presentLocalNotificationNow:note]; - - // Serialize it and store so we can delete it later - NSData* data = [NSKeyedArchiver archivedDataWithRootObject:note]; - NSString* notificationKey = [self buildNotificationKeyfromNotification:notificationId]; - [[NSUserDefaults standardUserDefaults] setObject:data forKey:notificationKey]; - [[NSUserDefaults standardUserDefaults] synchronize]; - - NSLog(@"Local notification was triggered: %@", notificationKey); - } -} - -- (void)clearNotificationFromNotificationsCenter:(NSString *)notificationId { - NSString* notificationKey = [self buildNotificationKeyfromNotification:notificationId]; - NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:notificationKey]; - if (data) { - UILocalNotification* notification = [NSKeyedUnarchiver unarchiveObjectWithData: data]; - - // delete the notification - [[UIApplication sharedApplication] cancelLocalNotification:notification]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:notificationKey]; - - NSLog(@"Local notification removed: %@", notificationKey); - - return; - } -} - -- (NSString *)buildNotificationKeyfromNotification:(NSString *)notificationId { - return [NSString stringWithFormat:@"%@.%@", [[NSBundle mainBundle] bundleIdentifier], notificationId]; -} - -- (NSString *)deviceTokenToString:(NSData *)deviceToken { - NSMutableString *result = [NSMutableString string]; - NSUInteger deviceTokenLength = deviceToken.length; - const unsigned char *bytes = deviceToken.bytes; - for (NSUInteger i = 0; i < deviceTokenLength; i++) { - [result appendFormat:@"%02x", bytes[i]]; - } - - return [result copy]; -} - -- (void)requestPermissionsWithCategories:(NSMutableSet *)categories { - UNAuthorizationOptions authOptions = (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert); - [UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { - if (error) { - - } else { - if (granted) { - [UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { - if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) { - [[UIApplication sharedApplication] registerForRemoteNotifications]; - } - }]; - } else { - - } - } - }]; -} - -- (void)emitNotificationActionForIdentifier:(NSString *)identifier responseInfo:(NSDictionary *)responseInfo userInfo:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { - NSString* completionKey = [NSString stringWithFormat:@"%@.%@", identifier, [NSString stringWithFormat:@"%d", (long)[[NSDate date] timeIntervalSince1970]]]; - NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier, @"completionKey": completionKey }]; - - // add text - NSString* text = [responseInfo objectForKey:UIUserNotificationActionResponseTypedTextKey]; - if (text != NULL) { - info[@"text"] = text; - } - - // add notification custom data - if (userInfo != NULL) { - info[@"notification"] = userInfo; - } - - // Emit event to the queue (in order to store the completion handler). if JS thread is ready, post it also to the notification center (to the bridge). - [[RNNotificationsBridgeQueue sharedInstance] postAction:info withCompletionKey:completionKey andCompletionHandler:completionHandler]; - - if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) { - [RNEventEmitter sendEvent:NotificationActionReceived body:userInfo]; - } -} - -- (void)registerPushKit { - // Create a push registry object - PKPushRegistry* pushKitRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; - - // Set the registry delegate to app delegate - pushKitRegistry.delegate = [[UIApplication sharedApplication] delegate]; - pushKitRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; -} - -- (void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type { - [RNEventEmitter sendEvent:PushKitRegistered body:@{@"pushKitToken": [self deviceTokenToString:credentials.token]}]; -} - -- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { -// [RNNotifications didReceiveRemoteNotification:payload.dictionaryPayload]; -} - @end diff --git a/RNNotifications/RNNotifications.xcodeproj/project.pbxproj b/RNNotifications/RNNotifications.xcodeproj/project.pbxproj index 28529ef69a616175d5e9af5f98e1b7a43a34bb65..b5a6c3971378fead22602bd6acd5772908b3bd15 100644 --- a/RNNotifications/RNNotifications.xcodeproj/project.pbxproj +++ b/RNNotifications/RNNotifications.xcodeproj/project.pbxproj @@ -18,10 +18,36 @@ 507DCCFA22CE3F04005D4E0B /* RNEventEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 50351F8D22CD782F000713B3 /* RNEventEmitter.h */; }; 507DCCFB22CE3F04005D4E0B /* RNCommandsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 50351F9622CD8604000713B3 /* RNCommandsHandler.h */; }; 507DCCFC22CE3F04005D4E0B /* RCTConvert+Notifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 50351F9322CD7FF1000713B3 /* RCTConvert+Notifications.h */; }; + 508CE7CB22D12B2600357815 /* RNNotificationsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE7CA22D12B2600357815 /* RNNotificationsTests.m */; }; + 508CE7CD22D12B2600357815 /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134814201AA4EA6300B7C361 /* libRNNotifications.a */; }; + 508CE7D522D12CCA00357815 /* RNNotificationEventHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CE7D322D12CCA00357815 /* RNNotificationEventHandler.h */; }; + 508CE7D622D12CCA00357815 /* RNNotificationEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE7D422D12CCA00357815 /* RNNotificationEventHandler.m */; }; + 508CE81422D12FC700357815 /* RNNotificationCenterListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE81322D12FC600357815 /* RNNotificationCenterListener.m */; }; + 508CE81622D12FF600357815 /* RNNotificationCenterListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CE81522D12FF500357815 /* RNNotificationCenterListener.h */; }; + 508CE81922D130B900357815 /* RNPushKitEventListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CE81722D130B900357815 /* RNPushKitEventListener.h */; }; + 508CE81A22D130B900357815 /* RNPushKitEventListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE81822D130B900357815 /* RNPushKitEventListener.m */; }; + 508CE81D22D1337200357815 /* RNPushKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CE81B22D1337200357815 /* RNPushKit.h */; }; + 508CE81E22D1337200357815 /* RNPushKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE81C22D1337200357815 /* RNPushKit.m */; }; + 508CE82222D1372E00357815 /* RNUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CE82022D1372E00357815 /* RNUtils.h */; }; + 508CE82322D1372E00357815 /* RNUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 508CE82122D1372E00357815 /* RNUtils.m */; }; + 50AD1FCA22D13ADB00E12362 /* RNPushKitEventHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 50AD1FC822D13ADB00E12362 /* RNPushKitEventHandler.h */; }; + 50AD1FCB22D13ADB00E12362 /* RNPushKitEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 50AD1FC922D13ADB00E12362 /* RNPushKitEventHandler.m */; }; + 50E49F0722D1E4E0007160C1 /* RNNotificationsStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 50E49F0522D1E4E0007160C1 /* RNNotificationsStore.h */; }; + 50E49F0822D1E4E0007160C1 /* RNNotificationsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E49F0622D1E4E0007160C1 /* RNNotificationsStore.m */; }; D85B37451CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */; }; D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 508CE7CE22D12B2600357815 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 58B511D31A9E6C8500147676 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 58B511DA1A9E6C8500147676; + remoteInfo = RNNotifications; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 58B511D91A9E6C8500147676 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -45,6 +71,25 @@ 50351F9422CD7FF1000713B3 /* RCTConvert+Notifications.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+Notifications.m"; sourceTree = ""; }; 50351F9622CD8604000713B3 /* RNCommandsHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCommandsHandler.h; sourceTree = ""; }; 50351F9722CD8604000713B3 /* RNCommandsHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCommandsHandler.m; sourceTree = ""; }; + 508CE7BB22D12B0A00357815 /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; + 508CE7BD22D12B0A00357815 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 508CE7C822D12B2600357815 /* RNNotificationsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNNotificationsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 508CE7CA22D12B2600357815 /* RNNotificationsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNotificationsTests.m; sourceTree = ""; }; + 508CE7CC22D12B2600357815 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 508CE7D322D12CCA00357815 /* RNNotificationEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNotificationEventHandler.h; sourceTree = ""; }; + 508CE7D422D12CCA00357815 /* RNNotificationEventHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNotificationEventHandler.m; sourceTree = ""; }; + 508CE81322D12FC600357815 /* RNNotificationCenterListener.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotificationCenterListener.m; sourceTree = ""; }; + 508CE81522D12FF500357815 /* RNNotificationCenterListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNotificationCenterListener.h; sourceTree = ""; }; + 508CE81722D130B900357815 /* RNPushKitEventListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNPushKitEventListener.h; sourceTree = ""; }; + 508CE81822D130B900357815 /* RNPushKitEventListener.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNPushKitEventListener.m; sourceTree = ""; }; + 508CE81B22D1337200357815 /* RNPushKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNPushKit.h; sourceTree = ""; }; + 508CE81C22D1337200357815 /* RNPushKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNPushKit.m; sourceTree = ""; }; + 508CE82022D1372E00357815 /* RNUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNUtils.h; sourceTree = ""; }; + 508CE82122D1372E00357815 /* RNUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNUtils.m; sourceTree = ""; }; + 50AD1FC822D13ADB00E12362 /* RNPushKitEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNPushKitEventHandler.h; sourceTree = ""; }; + 50AD1FC922D13ADB00E12362 /* RNPushKitEventHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNPushKitEventHandler.m; sourceTree = ""; }; + 50E49F0522D1E4E0007160C1 /* RNNotificationsStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNotificationsStore.h; sourceTree = ""; }; + 50E49F0622D1E4E0007160C1 /* RNNotificationsStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNotificationsStore.m; sourceTree = ""; }; D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotificationsBridgeQueue.m; sourceTree = ""; }; D85B37461CC05A1200DE9EB6 /* RNNotificationsBridgeQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNotificationsBridgeQueue.h; sourceTree = ""; }; D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotifications.m; sourceTree = ""; }; @@ -52,6 +97,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 508CE7C522D12B2600357815 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 508CE7CD22D12B2600357815 /* libRNNotifications.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 58B511D81A9E6C8500147676 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -70,22 +123,81 @@ name = Products; sourceTree = ""; }; + 508CE7BA22D12B0A00357815 /* Tests */ = { + isa = PBXGroup; + children = ( + 508CE7BB22D12B0A00357815 /* Tests.m */, + 508CE7BD22D12B0A00357815 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + 508CE7C922D12B2600357815 /* RNNotificationsTests */ = { + isa = PBXGroup; + children = ( + 508CE7CA22D12B2600357815 /* RNNotificationsTests.m */, + 508CE7CC22D12B2600357815 /* Info.plist */, + ); + path = RNNotificationsTests; + sourceTree = ""; + }; + 508CE81122D12F3C00357815 /* Notifications */ = { + isa = PBXGroup; + children = ( + 508CE7D322D12CCA00357815 /* RNNotificationEventHandler.h */, + 508CE7D422D12CCA00357815 /* RNNotificationEventHandler.m */, + 508CE81522D12FF500357815 /* RNNotificationCenterListener.h */, + 508CE81322D12FC600357815 /* RNNotificationCenterListener.m */, + ); + name = Notifications; + sourceTree = ""; + }; + 508CE81222D12F4300357815 /* PushKitNotifications */ = { + isa = PBXGroup; + children = ( + 508CE81B22D1337200357815 /* RNPushKit.h */, + 508CE81C22D1337200357815 /* RNPushKit.m */, + 508CE81722D130B900357815 /* RNPushKitEventListener.h */, + 508CE81822D130B900357815 /* RNPushKitEventListener.m */, + 50AD1FC822D13ADB00E12362 /* RNPushKitEventHandler.h */, + 50AD1FC922D13ADB00E12362 /* RNPushKitEventHandler.m */, + ); + name = PushKitNotifications; + sourceTree = ""; + }; + 508CE81F22D1371700357815 /* Helpers */ = { + isa = PBXGroup; + children = ( + 508CE82022D1372E00357815 /* RNUtils.h */, + 508CE82122D1372E00357815 /* RNUtils.m */, + ); + name = Helpers; + sourceTree = ""; + }; 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( + 508CE81222D12F4300357815 /* PushKitNotifications */, + 508CE81122D12F3C00357815 /* Notifications */, + 508CE81F22D1371700357815 /* Helpers */, 50351F9022CD7DF4000713B3 /* RNBridgeModule.h */, 50351F9122CD7DF4000713B3 /* RNBridgeModule.m */, - D85B37461CC05A1200DE9EB6 /* RNNotificationsBridgeQueue.h */, - D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */, + 50351F9622CD8604000713B3 /* RNCommandsHandler.h */, + 50351F9722CD8604000713B3 /* RNCommandsHandler.m */, D8A2F7561CB57F28002CC8F5 /* RNNotifications.h */, D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */, + 50E49F0522D1E4E0007160C1 /* RNNotificationsStore.h */, + 50E49F0622D1E4E0007160C1 /* RNNotificationsStore.m */, + D85B37461CC05A1200DE9EB6 /* RNNotificationsBridgeQueue.h */, + D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */, 50351F8D22CD782F000713B3 /* RNEventEmitter.h */, 50351F8E22CD782F000713B3 /* RNEventEmitter.m */, - 50351F9622CD8604000713B3 /* RNCommandsHandler.h */, - 50351F9722CD8604000713B3 /* RNCommandsHandler.m */, 50351F9322CD7FF1000713B3 /* RCTConvert+Notifications.h */, 50351F9422CD7FF1000713B3 /* RCTConvert+Notifications.m */, + 508CE7BA22D12B0A00357815 /* Tests */, + 508CE7C922D12B2600357815 /* RNNotificationsTests */, 134814211AA4EA7D00B7C361 /* Products */, + 508CE7C822D12B2600357815 /* RNNotificationsTests.xctest */, ); sourceTree = ""; }; @@ -96,8 +208,15 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 508CE81D22D1337200357815 /* RNPushKit.h in Headers */, + 50AD1FCA22D13ADB00E12362 /* RNPushKitEventHandler.h in Headers */, 507DCCF922CE3F04005D4E0B /* RNNotifications.h in Headers */, + 508CE7D522D12CCA00357815 /* RNNotificationEventHandler.h in Headers */, + 508CE81922D130B900357815 /* RNPushKitEventListener.h in Headers */, + 50E49F0722D1E4E0007160C1 /* RNNotificationsStore.h in Headers */, + 508CE81622D12FF600357815 /* RNNotificationCenterListener.h in Headers */, 507DCCF822CE3F04005D4E0B /* RNNotificationsBridgeQueue.h in Headers */, + 508CE82222D1372E00357815 /* RNUtils.h in Headers */, 507DCCFA22CE3F04005D4E0B /* RNEventEmitter.h in Headers */, 507DCCFB22CE3F04005D4E0B /* RNCommandsHandler.h in Headers */, 507DCCFC22CE3F04005D4E0B /* RCTConvert+Notifications.h in Headers */, @@ -108,6 +227,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 508CE7C722D12B2600357815 /* RNNotificationsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 508CE7D022D12B2600357815 /* Build configuration list for PBXNativeTarget "RNNotificationsTests" */; + buildPhases = ( + 508CE7C422D12B2600357815 /* Sources */, + 508CE7C522D12B2600357815 /* Frameworks */, + 508CE7C622D12B2600357815 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 508CE7CF22D12B2600357815 /* PBXTargetDependency */, + ); + name = RNNotificationsTests; + productName = RNNotificationsTests; + productReference = 508CE7C822D12B2600357815 /* RNNotificationsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 58B511DA1A9E6C8500147676 /* RNNotifications */ = { isa = PBXNativeTarget; buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNNotifications" */; @@ -135,6 +272,10 @@ LastUpgradeCheck = 0610; ORGANIZATIONNAME = Facebook; TargetAttributes = { + 508CE7C722D12B2600357815 = { + CreatedOnToolsVersion = 10.1; + ProvisioningStyle = Automatic; + }; 58B511DA1A9E6C8500147676 = { CreatedOnToolsVersion = 6.1.1; }; @@ -153,11 +294,30 @@ projectRoot = ""; targets = ( 58B511DA1A9E6C8500147676 /* RNNotifications */, + 508CE7C722D12B2600357815 /* RNNotificationsTests */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + 508CE7C622D12B2600357815 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ + 508CE7C422D12B2600357815 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 508CE7CB22D12B2600357815 /* RNNotificationsTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 58B511D71A9E6C8500147676 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -165,15 +325,101 @@ 50351F9822CD8604000713B3 /* RNCommandsHandler.m in Sources */, D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */, 50351F8F22CD782F000713B3 /* RNEventEmitter.m in Sources */, + 508CE81A22D130B900357815 /* RNPushKitEventListener.m in Sources */, 50351F9222CD7DF4000713B3 /* RNBridgeModule.m in Sources */, + 508CE81E22D1337200357815 /* RNPushKit.m in Sources */, D85B37451CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m in Sources */, + 508CE7D622D12CCA00357815 /* RNNotificationEventHandler.m in Sources */, + 50E49F0822D1E4E0007160C1 /* RNNotificationsStore.m in Sources */, + 508CE82322D1372E00357815 /* RNUtils.m in Sources */, 50351F9522CD7FF1000713B3 /* RCTConvert+Notifications.m in Sources */, + 50AD1FCB22D13ADB00E12362 /* RNPushKitEventHandler.m in Sources */, + 508CE81422D12FC700357815 /* RNNotificationCenterListener.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 508CE7CF22D12B2600357815 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 58B511DA1A9E6C8500147676 /* RNNotifications */; + targetProxy = 508CE7CE22D12B2600357815 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ + 508CE7D122D12B2600357815 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = RNNotificationsTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 508CE7D222D12B2600357815 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = RNNotificationsTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 58B511ED1A9E6C8500147676 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -283,6 +529,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 508CE7D022D12B2600357815 /* Build configuration list for PBXNativeTarget "RNNotificationsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 508CE7D122D12B2600357815 /* Debug */, + 508CE7D222D12B2600357815 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNNotifications" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/RNNotifications/RNNotificationsBridgeQueue.h b/RNNotifications/RNNotificationsBridgeQueue.h index 61ff05ba57e5baf5ea3570bfd44ea6924d892f17..b6294a9641c0cd97fcb1214ae94ff831b53e28d6 100644 --- a/RNNotifications/RNNotificationsBridgeQueue.h +++ b/RNNotifications/RNNotificationsBridgeQueue.h @@ -2,9 +2,7 @@ @interface RNNotificationsBridgeQueue : NSObject -@property BOOL jsIsReady; @property NSDictionary* openedRemoteNotification; -@property NSDictionary* openedLocalNotification; + (nonnull instancetype)sharedInstance; @@ -16,4 +14,4 @@ - (void)completeAction:(NSString *)completionKey; -@end \ No newline at end of file +@end diff --git a/RNNotifications/RNNotificationsBridgeQueue.m b/RNNotifications/RNNotificationsBridgeQueue.m index 9555f3fb457a02bd88215dc5671e398c92ff3eb9..747a2995bdc741f20c2b677ace742401badf4a14 100644 --- a/RNNotifications/RNNotificationsBridgeQueue.m +++ b/RNNotifications/RNNotificationsBridgeQueue.m @@ -21,7 +21,6 @@ NSMutableDictionary* actionCompletionHandlers; actionsQueue = [NSMutableArray new]; notificationsQueue = [NSMutableArray new]; actionCompletionHandlers = [NSMutableDictionary new]; - self.jsIsReady = NO; return self; } @@ -92,4 +91,4 @@ NSMutableDictionary* actionCompletionHandlers; } } -@end \ No newline at end of file +@end diff --git a/RNNotifications/RNNotificationsStore.h b/RNNotifications/RNNotificationsStore.h new file mode 100644 index 0000000000000000000000000000000000000000..9e4c19178b65cfa0128c0370b115dc835e55eb9d --- /dev/null +++ b/RNNotifications/RNNotificationsStore.h @@ -0,0 +1,5 @@ +#import + +@interface RNNotificationsStore : NSObject + +@end diff --git a/RNNotifications/RNNotificationsStore.m b/RNNotifications/RNNotificationsStore.m new file mode 100644 index 0000000000000000000000000000000000000000..164f0715ed6f5dbd2da50e05d9a22f3fffa914a1 --- /dev/null +++ b/RNNotifications/RNNotificationsStore.m @@ -0,0 +1,13 @@ +#import "RNNotificationsStore.h" + +@implementation RNNotificationsStore { + NSMutableDictionary* actionCompletionHandlers; +} + +- (instancetype)init { + actionCompletionHandlers = [NSMutableDictionary new]; + + return self; +} + +@end diff --git a/RNNotifications/RNNotificationsTests/Info.plist b/RNNotifications/RNNotificationsTests/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..6c40a6cd0c4af2f0d93b697fbfb066793681b045 --- /dev/null +++ b/RNNotifications/RNNotificationsTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/RNNotifications/RNNotificationsTests/RNNotificationsTests.m b/RNNotifications/RNNotificationsTests/RNNotificationsTests.m new file mode 100644 index 0000000000000000000000000000000000000000..bfb9fa6b3478a21c18559a1421dd71e0e7ab8248 --- /dev/null +++ b/RNNotifications/RNNotificationsTests/RNNotificationsTests.m @@ -0,0 +1,37 @@ +// +// RNNotificationsTests.m +// RNNotificationsTests +// +// Created by Yogev Ben David on 06/07/2019. +// Copyright © 2019 Facebook. All rights reserved. +// + +#import + +@interface RNNotificationsTests : XCTestCase + +@end + +@implementation RNNotificationsTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/RNNotifications/RNPushKit.h b/RNNotifications/RNPushKit.h new file mode 100644 index 0000000000000000000000000000000000000000..63e1669a7512bc65f1c0c91c66c1d4ec9ec7688b --- /dev/null +++ b/RNNotifications/RNPushKit.h @@ -0,0 +1,9 @@ +#import +#import "RNPushKitEventListener.h" +@import PushKit; + +@interface RNPushKit : NSObject + +- (instancetype)initWithPushKitEventListener:(RNPushKitEventListener *)pushKitEventListener; + +@end diff --git a/RNNotifications/RNPushKit.m b/RNNotifications/RNPushKit.m new file mode 100644 index 0000000000000000000000000000000000000000..cc9a5bc66fe0a1100fdf5b46dd95b0a38e4b5f77 --- /dev/null +++ b/RNNotifications/RNPushKit.m @@ -0,0 +1,19 @@ +#import "RNPushKit.h" + +@implementation RNPushKit { + RNPushKitEventListener* _pushKitEventListener; +} + +- (instancetype)initWithPushKitEventListener:(RNPushKitEventListener *)pushKitEventListener { + self = [super init]; + + _pushKitEventListener = pushKitEventListener; + + PKPushRegistry* pushKitRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; + pushKitRegistry.delegate = pushKitEventListener; + pushKitRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; + + return self; +} + +@end diff --git a/RNNotifications/RNPushKitEventHandler.h b/RNNotifications/RNPushKitEventHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..c1c0a388d0b0c3dfd2eeb47bd15bd4b47a04ef52 --- /dev/null +++ b/RNNotifications/RNPushKitEventHandler.h @@ -0,0 +1,8 @@ +#import +#import "RNNotificationEventHandler.h" + +@interface RNPushKitEventHandler : RNNotificationEventHandler + +- (void)registeredWithToken:(NSString *)token; + +@end diff --git a/RNNotifications/RNPushKitEventHandler.m b/RNNotifications/RNPushKitEventHandler.m new file mode 100644 index 0000000000000000000000000000000000000000..e44e6d079aed95bed14b6c4aa98998e66569ce0d --- /dev/null +++ b/RNNotifications/RNPushKitEventHandler.m @@ -0,0 +1,10 @@ +#import "RNPushKitEventHandler.h" +#import "RNEventEmitter.h" + +@implementation RNPushKitEventHandler + +- (void)registeredWithToken:(NSString *)token { + [RNEventEmitter sendEvent:PushKitRegistered body:@{@"pushKitToken": token}]; +} + +@end diff --git a/RNNotifications/RNPushKitEventListener.h b/RNNotifications/RNPushKitEventListener.h new file mode 100644 index 0000000000000000000000000000000000000000..7cb5be8f3a01aebbabf411b037db798bd5f3fda1 --- /dev/null +++ b/RNNotifications/RNPushKitEventListener.h @@ -0,0 +1,9 @@ +#import +@import PushKit; +#import "RNPushKitEventHandler.h" + +@interface RNPushKitEventListener : NSObject + +- (instancetype)initWithPushKitEventHandler:(RNPushKitEventHandler *)pushKitEventHandler; + +@end diff --git a/RNNotifications/RNPushKitEventListener.m b/RNNotifications/RNPushKitEventListener.m new file mode 100644 index 0000000000000000000000000000000000000000..f9548baebd41ef13dcab260860091e5d295bf840 --- /dev/null +++ b/RNNotifications/RNPushKitEventListener.m @@ -0,0 +1,27 @@ +#import "RNPushKitEventListener.h" +#import "RNEventEmitter.h" +#import "RNUtils.h" + +@implementation RNPushKitEventListener { + PKPushRegistry* _pushRegistry; + RNPushKitEventHandler* _pushKitEventHandler; +} + +- (instancetype)initWithPushKitEventHandler:(RNPushKitEventHandler *)pushKitEventHandler { + self = [super init]; + + _pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; + _pushKitEventHandler = pushKitEventHandler; + + return self; +} + +- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type { + [_pushKitEventHandler registeredWithToken:[RNUtils deviceTokenToString:credentials.token]]; +} + +- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { + [_pushKitEventHandler didOpenNotificationPayload:payload.dictionaryPayload]; +} + +@end diff --git a/RNNotifications/RNUtils.h b/RNNotifications/RNUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..07a81c01272ed95f98fe0dcf5247d46e2414ae46 --- /dev/null +++ b/RNNotifications/RNUtils.h @@ -0,0 +1,7 @@ +#import + +@interface RNUtils : NSObject + ++ (NSString *)deviceTokenToString:(NSData *)deviceToken; + +@end diff --git a/RNNotifications/RNUtils.m b/RNNotifications/RNUtils.m new file mode 100644 index 0000000000000000000000000000000000000000..08c75daf1f154cfb393eb187215398425af69bbe --- /dev/null +++ b/RNNotifications/RNUtils.m @@ -0,0 +1,16 @@ +#import "RNUtils.h" + +@implementation RNUtils + ++ (NSString *)deviceTokenToString:(NSData *)deviceToken { + NSMutableString *result = [NSMutableString string]; + NSUInteger deviceTokenLength = deviceToken.length; + const unsigned char *bytes = deviceToken.bytes; + for (NSUInteger i = 0; i < deviceTokenLength; i++) { + [result appendFormat:@"%02x", bytes[i]]; + } + + return [result copy]; +} + +@end diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000000000000000000000000000000000000..07e3b738f243b4af2a018709795d2fb1219acc4e --- /dev/null +++ b/babel.config.js @@ -0,0 +1,12 @@ +module.exports = function (api) { + api && api.cache(false); + return { + presets: [ + "module:metro-react-native-babel-preset" + ], + plugins: [ + "@babel/plugin-proposal-export-namespace-from", + "@babel/plugin-proposal-export-default-from" + ] + }; +} diff --git a/e2e/BottomTabs.test.js b/e2e/BottomTabs.test.js new file mode 100644 index 0000000000000000000000000000000000000000..48ad6c39505f398b7f256b2c2b7aa8a505ad4974 --- /dev/null +++ b/e2e/BottomTabs.test.js @@ -0,0 +1,15 @@ +const Utils = require('./Utils'); +const { elementByLabel, elementById, sleep } = Utils; +describe('BottomTabs', () => { + beforeEach(async () => { + await device.relaunchApp(); + // await elementById(TestIDs.BOTTOM_TABS_BTN).tap(); + // await expect(elementByLabel('First Tab')).toBeVisible(); + }); + + it('switch to tab by index', async () => { + // await elementById(TestIDs.SWITCH_TAB_BY_INDEX_BTN).tap(); + await expect(elementByLabel('First Tab')).toBeNotVisible(); + await expect(elementByLabel('Second Tab')).toBeVisible(); + }); +}); diff --git a/e2e/config.json b/e2e/config.json new file mode 100644 index 0000000000000000000000000000000000000000..4dac170d3611e1aedf2d44b49c675b6ded1b78c1 --- /dev/null +++ b/e2e/config.json @@ -0,0 +1,6 @@ +{ + "setupTestFrameworkScriptFile" : "./init.js", + "testEnvironment": "node", + "bail": true, + "verbose": true +} diff --git a/e2e/init.js b/e2e/init.js new file mode 100644 index 0000000000000000000000000000000000000000..a301c90e6cfc5722bfd9ec167737e2aad2e619ae --- /dev/null +++ b/e2e/init.js @@ -0,0 +1,30 @@ +const detox = require('detox'); +const config = require('../package.json').detox; +const exec = require('shell-utils').exec; +const adapter = require('detox/runners/jest/adapter'); + +jest.setTimeout(300000); +jasmine.getEnv().addReporter(adapter); + +beforeAll(async () => { + await detox.init(config, {launchApp: false}); + disableAndroidEmulatorAnimations(); +}); + +afterAll(async () => { + await adapter.afterAll(); + await detox.cleanup(); +}); + +beforeEach(async () => { + await adapter.beforeEach(); +}); + +function disableAndroidEmulatorAnimations() { + if (device.getPlatform() === 'android') { + const deviceId = device._deviceId; + exec.execAsync(`adb -s ${deviceId} shell settings put global window_animation_scale 0.0`); + exec.execAsync(`adb -s ${deviceId} shell settings put global transition_animation_scale 0.0`); + exec.execAsync(`adb -s ${deviceId} shell settings put global animator_duration_scale 0.0`); + } +} diff --git a/example/index.ios.js b/example/index.ios.js index 5a2d5c3cf348398777109a160d19ecc4e0de0f24..3370901c8493107a61c5121a52f997516d55f66d 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -6,41 +6,41 @@ import { AppRegistry, StyleSheet, - Text, - View + View, + Text } from 'react-native'; import React, {Component} from 'react'; import NotificationsIOS, { NotificationAction, NotificationCategory } from 'react-native-notifications'; let upvoteAction = new NotificationAction({ - activationMode: "background", + activationMode: 'background', title: String.fromCodePoint(0x1F44D), - identifier: "UPVOTE_ACTION" + identifier: 'UPVOTE_ACTION' }, (action, completed) => { - NotificationsIOS.log("ACTION RECEIVED"); + NotificationsIOS.log('ACTION RECEIVED'); NotificationsIOS.log(JSON.stringify(action)); completed(); }); let replyAction = new NotificationAction({ - activationMode: "background", - title: "Reply", - behavior: "textInput", + activationMode: 'background', + title: 'Reply', + behavior: 'textInput', authenticationRequired: true, - identifier: "REPLY_ACTION" + identifier: 'REPLY_ACTION' }, (action, completed) => { - console.log("ACTION RECEIVED"); + console.log('ACTION RECEIVED'); console.log(action); completed(); }); let cat = new NotificationCategory({ - identifier: "SOME_CATEGORY", + identifier: 'SOME_CATEGORY', actions: [upvoteAction, replyAction], - context: "default" + context: 'default' }); class NotificationsExampleApp extends Component { @@ -61,26 +61,26 @@ class NotificationsExampleApp extends Component { } onPushRegistered(deviceToken) { - console.log("Device Token Received: " + deviceToken); + console.log('Device Token Received: ' + deviceToken); } onPushKitRegistered(deviceToken) { - console.log("PushKit Token Received: " + deviceToken); + console.log('PushKit Token Received: ' + deviceToken); } onNotificationReceivedForeground(notification) { - console.log("Notification Received Foreground: " + JSON.stringify(notification)); + console.log('Notification Received Foreground: ' + JSON.stringify(notification)); } onNotificationReceivedBackground(notification) { - NotificationsIOS.log("Notification Received Background: " + JSON.stringify(notification)); + NotificationsIOS.log('Notification Received Background: ' + JSON.stringify(notification)); let localNotification = NotificationsIOS.localNotification({ - alertBody: "Received background notificiation!", - alertTitle: "Local Notification Title", - alertAction: "Click here to open", - soundName: "chime.aiff", - category: "SOME_CATEGORY", + alertBody: 'Received background notificiation!', + alertTitle: 'Local Notification Title', + alertAction: 'Click here to open', + soundName: 'chime.aiff', + category: 'SOME_CATEGORY', userInfo: notification.getData() }); @@ -88,13 +88,13 @@ class NotificationsExampleApp extends Component { // add the following line to the notification payload: // fireDate: new Date(Date.now() + (10 * 1000)).toISOString() - // NotificationsIOS.backgroundTimeRemaining(time => NotificationsIOS.log("remaining background time: " + time)); + // NotificationsIOS.backgroundTimeRemaining(time => NotificationsIOS.log('remaining background time: ' + time)); // NotificationsIOS.cancelLocalNotification(localNotification); } onNotificationOpened(notification) { - console.log("Notification Opened: " + JSON.stringify(notification)); + console.log('Notification Opened: ' + JSON.stringify(notification)); } render() { diff --git a/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj b/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj index 449308513c3ad761c2390a14d42264f871f1c9a2..033446f1486a2543822261d7a4faee951073900b 100644 --- a/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj +++ b/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj @@ -28,6 +28,41 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8; + remoteInfo = jsi; + }; + 50E49F4222D1F06C007160C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EDEBC73B214B45A300DD5AC8; + remoteInfo = jsiexecutor; + }; + 50E49F4422D1F06C007160C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ED296FB6214C9A0900B7C4FE; + remoteInfo = "jsi-tvOS"; + }; + 50E49F4622D1F06C007160C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ED296FEE214C9CF800B7C4FE; + remoteInfo = "jsiexecutor-tvOS"; + }; + 50E49F4A22D1F06C007160C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D85498C21D97B31100DEEE06 /* RNNotifications.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 508CE7C822D12B2600357815; + remoteInfo = RNNotificationsTests; + }; 50F1F05F22CE3A6100FD5829 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -70,20 +105,6 @@ remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; remoteInfo = "cxxreact-tvOS"; }; - 50F1F06B22CE3A6100FD5829 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4; - remoteInfo = jschelpers; - }; - 50F1F06D22CE3A6100FD5829 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4; - remoteInfo = "jschelpers-tvOS"; - }; 50F1F06F22CE3A6100FD5829 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -126,20 +147,6 @@ remoteGlobalIDString = 3D383D621EBD27B9005632C8; remoteInfo = "double-conversion-tvOS"; }; - 50F1F07B22CE3A6100FD5829 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 9936F3131F5F2E4B0010BF04; - remoteInfo = privatedata; - }; - 50F1F07D22CE3A6100FD5829 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04; - remoteInfo = "privatedata-tvOS"; - }; 50F1F08922CE3AA000FD5829 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */; @@ -358,16 +365,16 @@ 50F1F06622CE3A6100FD5829 /* libyoga.a */, 50F1F06822CE3A6100FD5829 /* libcxxreact.a */, 50F1F06A22CE3A6100FD5829 /* libcxxreact.a */, - 50F1F06C22CE3A6100FD5829 /* libjschelpers.a */, - 50F1F06E22CE3A6100FD5829 /* libjschelpers.a */, 50F1F07022CE3A6100FD5829 /* libjsinspector.a */, 50F1F07222CE3A6100FD5829 /* libjsinspector-tvOS.a */, 50F1F07422CE3A6100FD5829 /* libthird-party.a */, 50F1F07622CE3A6100FD5829 /* libthird-party.a */, 50F1F07822CE3A6100FD5829 /* libdouble-conversion.a */, 50F1F07A22CE3A6100FD5829 /* libdouble-conversion.a */, - 50F1F07C22CE3A6100FD5829 /* libprivatedata.a */, - 50F1F07E22CE3A6100FD5829 /* libprivatedata-tvOS.a */, + 50E49F4122D1F06C007160C1 /* libjsi.a */, + 50E49F4322D1F06C007160C1 /* libjsiexecutor.a */, + 50E49F4522D1F06C007160C1 /* libjsi-tvOS.a */, + 50E49F4722D1F06C007160C1 /* libjsiexecutor-tvOS.a */, ); name = Products; sourceTree = ""; @@ -503,6 +510,7 @@ isa = PBXGroup; children = ( D85498D11D97B31100DEEE06 /* libRNNotifications.a */, + 50E49F4B22D1F06C007160C1 /* RNNotificationsTests.xctest */, ); name = Products; sourceTree = ""; @@ -602,6 +610,41 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + 50E49F4122D1F06C007160C1 /* libjsi.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsi.a; + remoteRef = 50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 50E49F4322D1F06C007160C1 /* libjsiexecutor.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsiexecutor.a; + remoteRef = 50E49F4222D1F06C007160C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 50E49F4522D1F06C007160C1 /* libjsi-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsi-tvOS.a"; + remoteRef = 50E49F4422D1F06C007160C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 50E49F4722D1F06C007160C1 /* libjsiexecutor-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsiexecutor-tvOS.a"; + remoteRef = 50E49F4622D1F06C007160C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 50E49F4B22D1F06C007160C1 /* RNNotificationsTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = RNNotificationsTests.xctest; + remoteRef = 50E49F4A22D1F06C007160C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 50F1F06022CE3A6100FD5829 /* libReact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -644,20 +687,6 @@ remoteRef = 50F1F06922CE3A6100FD5829 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 50F1F06C22CE3A6100FD5829 /* libjschelpers.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libjschelpers.a; - remoteRef = 50F1F06B22CE3A6100FD5829 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 50F1F06E22CE3A6100FD5829 /* libjschelpers.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libjschelpers.a; - remoteRef = 50F1F06D22CE3A6100FD5829 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 50F1F07022CE3A6100FD5829 /* libjsinspector.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -700,20 +729,6 @@ remoteRef = 50F1F07922CE3A6100FD5829 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 50F1F07C22CE3A6100FD5829 /* libprivatedata.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libprivatedata.a; - remoteRef = 50F1F07B22CE3A6100FD5829 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 50F1F07E22CE3A6100FD5829 /* libprivatedata-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libprivatedata-tvOS.a"; - remoteRef = 50F1F07D22CE3A6100FD5829 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 50F1F08A22CE3AA000FD5829 /* libRCTActionSheet.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/example/ios/NotificationsExampleApp/AppDelegate.m b/example/ios/NotificationsExampleApp/AppDelegate.m index 26367846b7a39c5f70199a0a5390048ec7be6685..9262ad48e1be9db0c972e7d869b8c4d720f7547c 100644 --- a/example/ios/NotificationsExampleApp/AppDelegate.m +++ b/example/ios/NotificationsExampleApp/AppDelegate.m @@ -12,7 +12,7 @@ { NSURL *jsCodeLocation; - jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; + jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"NotificationsExampleApp" @@ -25,21 +25,12 @@ rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; + + [[RNNotifications sharedInstance] initialize]; + return YES; } -// PushKit API Example -- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type -{ - [[RNNotifications sharedInstance] didUpdatePushCredentials:credentials forType:type]; -} - -- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type -{ -// [[RNNotifications sharedInstance] didReceiveRemoteNotification:payload.dictionaryPayload]; -} - - // Required to register for notifications - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { @@ -51,28 +42,4 @@ [[RNNotifications sharedInstance] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; } - -// Required for the notification event. -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification { -// [[RNNotifications sharedInstance] didReceiveRemoteNotification:notification]; -} - -// Required for the localNotification event. -- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification -{ -// [[RNNotifications sharedInstance] didReceiveLocalNotification:notification]; -} - - -// Required for the notification actions. -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler -{ - [[RNNotifications sharedInstance] handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler]; -} - -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler -{ - [[RNNotifications sharedInstance] handleActionWithIdentifier:identifier forRemoteNotification:userInfo withResponseInfo:responseInfo completionHandler:completionHandler]; -} - @end diff --git a/index.js b/index.js new file mode 100644 index 0000000000000000000000000000000000000000..c38e7f06d4a0bbcb488ef027d8c265db95027ac6 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +require('./example/index'); \ No newline at end of file diff --git a/index.android.js b/lib/src/index.android.js similarity index 100% rename from index.android.js rename to lib/src/index.android.js diff --git a/index.ios.js b/lib/src/index.ios.js similarity index 100% rename from index.ios.js rename to lib/src/index.ios.js diff --git a/notification.android.js b/lib/src/notification.android.js similarity index 100% rename from notification.android.js rename to lib/src/notification.android.js diff --git a/notification.ios.js b/lib/src/notification.ios.js similarity index 100% rename from notification.ios.js rename to lib/src/notification.ios.js diff --git a/metro.config.js b/metro.config.js index f7b069258032b546aaad74cdd89eaae3da66fa41..bf0faa48a6bc56386ed30d1b685e81670c83562b 100644 --- a/metro.config.js +++ b/metro.config.js @@ -1,6 +1,14 @@ module.exports = { projectRoot: `${__dirname}/example`, watchFolders: [ - __dirname - ] + __dirname, + ], + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: false, + }, + }) + } }; diff --git a/package.json b/package.json index 39ddcb5ca4a30b4aaff5e9bf037e7531b9eb2d52..2a9f248321c376ad840ee4660ae0c230eaca41a9 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,12 @@ "actionable-notifications", "interactive-notifications" ], + "main": "lib/src/index", "scripts": { "pretest": "./node_modules/.bin/eslint *.js test", "test": "./node_modules/.bin/mocha --compilers js:babel-register --reporter spec \"test/*.spec.js\"", - "start": "node ./scripts/start" + "start": "node ./scripts/start", + "test-e2e-ios": "node ./scripts/test-e2e --ios" }, "nativePackage": true, "dependencies": { @@ -34,9 +36,13 @@ "react-native": ">=0.25.1" }, "devDependencies": { + "@types/react": "16.x.x", + "@types/react-native": "0.57.7", + "@types/react-test-renderer": "16.x.x", + "@babel/plugin-proposal-export-default-from": "7.2.0", + "@babel/plugin-proposal-export-namespace-from": "7.2.0", + "typescript": "3.2.2", "babel-eslint": "9.0.0", - "babel-preset-react-native": "^1.9.0", - "babel-register": "^6.7.2", "chai": "^3.5.0", "chokidar-cli": "^1.2.0", "eslint": "6.0.1", @@ -45,8 +51,11 @@ "sinon": "^1.17.3", "sinon-chai": "^2.8.0", "shell-utils": "1.x.x", - "react-native": "0.57.7", - "react": "16.8.6" + "react-native": "0.60.0", + "react": "16.8.6", + "detox": "12.x.x", + "jest": "24.8.0", + "metro-react-native-babel-preset": "0.55.x" }, "publishConfig": { "registry": "https://registry.npmjs.org/" @@ -59,9 +68,59 @@ "bugs": { "url": "https://github.com/wix/react-native-notifications/issues" }, - "babel": { - "presets": [ - "react-native" + "detox": { + "test-runner": "jest", + "specs": "", + "configurations": { + "ios.none": { + "binaryPath": "playground/ios/DerivedData/playground/Build/Products/Debug-iphonesimulator/playground.app", + "type": "ios.none", + "name": "iPhone X", + "session": { + "server": "ws://localhost:8099", + "sessionId": "playground" + } + }, + "ios.sim.debug": { + "binaryPath": "example/ios/DerivedData/NotificationsExampleApp/Build/Products/Debug-iphonesimulator/NotificationsExampleApp.app", + "build": "RCT_NO_LAUNCH_PACKAGER=true xcodebuild build -scheme NotificationsExampleApp -project example/ios/NotificationsExampleApp.xcodeproj -sdk iphonesimulator -configuration Debug -derivedDataPath example/ios/DerivedData/NotificationsExampleApp ONLY_ACTIVE_ARCH=YES -quiet -UseModernBuildSystem=NO", + "type": "ios.simulator", + "name": "iPhone X" + }, + "ios.sim.release": { + "binaryPath": "playground/ios/DerivedData/playground/Build/Products/Release-iphonesimulator/playground.app", + "build": "RCT_NO_LAUNCH_PACKAGER=true xcodebuild build -scheme playground_release -project playground/ios/playground.xcodeproj -sdk iphonesimulator -configuration Release -derivedDataPath playground/ios/DerivedData/playground ONLY_ACTIVE_ARCH=YES -quiet -UseModernBuildSystem=NO", + "type": "ios.simulator", + "name": "iPhone X" + } + } + }, + "jest": { + "preset": "react-native", + "transform": { + "^.+\\.js$": "/node_modules/react-native/jest/preprocessor.js" + }, + "roots": [ + "/node_modules/" + ], + "collectCoverageFrom": [ + "lib/dist/**/*.js", + "integration/**/*.js", + "!lib/dist/index.js", + "!lib/dist/Navigation.js", + "!lib/dist/adapters/**/*", + "!lib/dist/interfaces/**/*", + "!lib/dist/**/*.test.*", + "!integration/**/*.test.*", + "!integration/*.test.*" + ], + "resetMocks": true, + "resetModules": true, + "coverageReporters": [ + "json", + "lcov", + "text", + "html" ] } } diff --git a/scripts/Utils.js b/scripts/Utils.js new file mode 100644 index 0000000000000000000000000000000000000000..938745504f7ee07180e13f6bb92e1d84b8021d93 --- /dev/null +++ b/scripts/Utils.js @@ -0,0 +1,18 @@ +const exec = require('shell-utils').exec; + +module.exports = { + elementByLabel: (label) => { + return element(by.text(label)); + }, + elementById: (id) => { + return element(by.id(id)); + }, + tapBackIos: () => { + try { + return element(by.traits(['button']).and(by.label('Back'))).atIndex(0).tap(); + } catch (err) { + return element(by.type('_UIModernBarButton').and(by.label('Back'))).tap(); + } + }, + sleep: ms => new Promise(res => setTimeout(res, ms)) +}; diff --git a/scripts/test-e2e.js b/scripts/test-e2e.js new file mode 100644 index 0000000000000000000000000000000000000000..248b848d749e9f649f6591ccee2e8d9f4ccd8d11 --- /dev/null +++ b/scripts/test-e2e.js @@ -0,0 +1,23 @@ +const _ = require('lodash'); +const exec = require('shell-utils').exec; + +const android = _.includes(process.argv, '--android'); +const release = _.includes(process.argv, '--release'); +const skipBuild = _.includes(process.argv, '--skipBuild'); +const headless = _.includes(process.argv, '--headless'); +const multi = _.includes(process.argv, '--multi'); + +run(); + +function run() { + const prefix = android ? `android.emu` : `ios.sim`; + const suffix = release ? `release` : `debug`; + const configuration = `${prefix}.${suffix}`; + const headless$ = android ? headless ? `--headless` : `` : ``; + const workers = multi ? 3 : 1; + + if (!skipBuild) { + exec.execSync(`detox build --configuration ${configuration}`); + } + exec.execSync(`detox test --loglevel verbose --configuration ${configuration} ${headless$} ${!android ? `-w ${workers}` : ``}`); //-f "ScreenStyle.test.js" --loglevel trace +}