diff --git a/node_modules/react-native-notifications/RNNotifications/RNNotificationEventHandler.m b/node_modules/react-native-notifications/RNNotifications/RNNotificationEventHandler.m index edc4fd4..694f01f 100644 --- a/node_modules/react-native-notifications/RNNotifications/RNNotificationEventHandler.m +++ b/node_modules/react-native-notifications/RNNotifications/RNNotificationEventHandler.m @@ -3,6 +3,8 @@ #import "RNNotificationUtils.h" #import "RCTConvert+RNNotifications.h" #import "RNNotificationParser.h" +#import +#import "SecureStorage.h" @implementation RNNotificationEventHandler { RNNotificationsStore* _store; @@ -28,9 +30,140 @@ - (void)didReceiveForegroundNotification:(UNNotification *)notification withComp [RNEventEmitter sendEvent:RNNotificationReceivedForeground body:[RNNotificationParser parseNotification:notification]]; } +/* + * Generate a random alphanumeric string to message id +*/ +-(NSString *)random:(int)len { + NSString *letters = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + NSMutableString *randomString = [NSMutableString stringWithCapacity:len]; + + for (int i=0; i 0) { + unichar last = [host characterAtIndex:[host length] - 1]; + if (last == '/') { + host = [host substringToIndex:[host length] - 1]; + } + } + return host; +} + +- (NSString *)stringToHex:(NSString *)string +{ + char *utf8 = (char *)[string UTF8String]; + NSMutableString *hex = [NSMutableString string]; + while (*utf8) [hex appendFormat:@"%02X", *utf8++ & 0x00FF]; + + return [[NSString stringWithFormat:@"%@", hex] lowercaseString]; +} + +- (NSDictionary *) retrieveCredentialsForServer:(NSString *)serverURL { + // AppGroup MMKV + NSString *groupDir = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppGroup"]].path; + + // Make sure MMKV is using the group directory + [MMKV initializeMMKV:nil groupDir:groupDir logLevel:MMKVLogNone]; + + // Start the MMKV container + __block MMKV *mmkv; + SecureStorage *secureStorage = [[SecureStorage alloc] init]; + + // https://github.com/ammarahm-ed/react-native-mmkv-storage/blob/master/src/loader.js#L31 + [secureStorage getSecureKey:[self stringToHex:@"com.MMKV.default"] callback:^(NSArray *response) { + // error handling + if ([response objectAtIndex:0] != [NSNull null]) { + return; + } + NSString *key = [response objectAtIndex:1]; + NSData *cryptKey = [key dataUsingEncoding:NSUTF8StringEncoding]; + mmkv = [MMKV mmkvWithID:@"default" cryptKey:cryptKey mode:MMKVMultiProcess]; + }]; + + if (!mmkv) { + return @{ + @"userId": @"", + @"userToken": @"" + }; + } + // Get credentials + NSString *TOKEN_KEY = @"reactnativemeteor_usertoken"; + NSString *userId = [mmkv getStringForKey:[NSString stringWithFormat:@"%@-%@", TOKEN_KEY, serverURL]]; + NSString *userToken = [mmkv getStringForKey:[NSString stringWithFormat:@"%@-%@", TOKEN_KEY, userId]]; + + // Retrive a NSDictionary with the credentials + return @{ + @"userId": userId, + @"userToken": userToken + }; +} + - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(void))completionHandler { - [_store setActionCompletionHandler:completionHandler withCompletionKey:response.notification.request.identifier]; - [RNEventEmitter sendEvent:RNNotificationOpened body:[RNNotificationParser parseNotificationResponse:response]]; + // if notification response is a REPLY_ACTION + if ([response.actionIdentifier isEqualToString:@"REPLY_ACTION"]) { + // convert notification data to dictionary payload + NSDictionary *notification = [RCTConvert UNNotificationPayload:response.notification]; + + // parse ejson from notification + NSData *ejsonData = [[notification valueForKey:@"ejson"] dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + NSDictionary *ejson = [NSJSONSerialization JSONObjectWithData:ejsonData options:kNilOptions error:&error]; + + // data from notification + NSString *host = [ejson valueForKey:@"host"]; + NSString *rid = [ejson valueForKey:@"rid"]; + + // msg on textinput of notification + NSString *msg = [(UNTextInputNotificationResponse *)response userText]; + + // get credentials + NSDictionary *credentials = [self retrieveCredentialsForServer:[self serverURL:host]]; + NSString *userId = [credentials valueForKey:@"userId"]; + NSString *token = [credentials valueForKey:@"userToken"]; + + // background task - we need this because fetch doesn't work if app is closed/killed + UIApplication *app = [UIApplication sharedApplication]; + __block UIBackgroundTaskIdentifier task = [app beginBackgroundTaskWithExpirationHandler:^{ + [app endBackgroundTask:task]; + task = UIBackgroundTaskInvalid; + }]; + // we use global queue to make requests with app closed/killed + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // we make a synchronous request to post new message + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/api/v1/chat.sendMessage", [self serverURL:host]]]]; + + NSString *message = [NSString stringWithFormat:@"{ \"message\": { \"_id\": \"%@\", \"msg\": \"%@\", \"rid\": \"%@\" } }", [self random:17], msg, rid]; + + [request setHTTPMethod:@"POST"]; + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request addValue:userId forHTTPHeaderField:@"x-user-id"]; + [request addValue:token forHTTPHeaderField:@"x-auth-token"]; + [request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding]]; + + NSURLResponse *response = nil; + NSError *error = nil; + NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; + + // end background task + [app endBackgroundTask:task]; + task = UIBackgroundTaskInvalid; + + // complete notification response + completionHandler(); + }); + } else { + // We only set initial notification and emit event to JS when not is a reply action + [_store setActionCompletionHandler:completionHandler withCompletionKey:response.notification.request.identifier]; + [RNEventEmitter sendEvent:RNNotificationOpened body:[RNNotificationParser parseNotificationResponse:response]]; + } } @end diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java index 524ff07..70f22d5 100644 --- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java +++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java @@ -31,7 +31,7 @@ public class PushNotification implements IPushNotification { final protected AppLifecycleFacade mAppLifecycleFacade; final protected AppLaunchHelper mAppLaunchHelper; final protected JsIOHelper mJsIOHelper; - final protected PushNotificationProps mNotificationProps; + protected PushNotificationProps mNotificationProps; final protected AppVisibilityListener mAppVisibilityListener = new AppVisibilityListener() { @Override public void onAppVisible() { diff --git a/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java b/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java index f9c858b..94ea188 100644 --- a/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java +++ b/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java @@ -2,8 +2,8 @@ package com.wix.reactnativenotifications; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v4.app.NotificationManagerCompat; +import androidx.annotation.NonNull; +import androidx.core.app.NotificationManagerCompat; public abstract class NotificationManagerCompatFacade { public static NotificationManagerCompat from(@NonNull Context context) {