RNNotifications.m 22.4 KB
Newer Older
Lidan Hifi's avatar
Lidan Hifi committed
1 2

#import <UIKit/UIKit.h>
3
#import <PushKit/PushKit.h>
Lidan Hifi's avatar
Lidan Hifi committed
4 5
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
Lidan Hifi's avatar
Lidan Hifi committed
6
#import "RNNotifications.h"
7
#import "RCTConvert.h"
Lidan Hifi's avatar
Lidan Hifi committed
8
#import "RCTUtils.h"
9
#import "RNNotificationsBridgeQueue.h"
Lidan Hifi's avatar
Lidan Hifi committed
10

11 12
NSString* const RNNotificationCreateAction = @"CREATE";
NSString* const RNNotificationClearAction = @"CLEAR";
Lidan Hifi's avatar
Lidan Hifi committed
13

14
NSString* const RNNotificationsRegistered = @"RNNotificationsRegistered";
15
NSString* const RNNotificationsRegistrationFailed = @"RNNotificationsRegistrationFailed";
16
NSString* const RNPushKitRegistered = @"RNPushKitRegistered";
17 18 19 20
NSString* const RNNotificationReceivedForeground = @"RNNotificationReceivedForeground";
NSString* const RNNotificationReceivedBackground = @"RNNotificationReceivedBackground";
NSString* const RNNotificationOpened = @"RNNotificationOpened";
NSString* const RNNotificationActionTriggered = @"RNNotificationActionTriggered";
Lidan Hifi's avatar
Lidan Hifi committed
21

22
/*
23
 * Converters for Interactive Notifications
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 */
@implementation RCTConvert (UIUserNotificationActivationMode)
RCT_ENUM_CONVERTER(UIUserNotificationActivationMode, (@{
                                                        @"foreground": @(UIUserNotificationActivationModeForeground),
                                                        @"background": @(UIUserNotificationActivationModeBackground)
                                                        }), UIUserNotificationActivationModeForeground, integerValue)
@end

@implementation RCTConvert (UIUserNotificationActionContext)
RCT_ENUM_CONVERTER(UIUserNotificationActionContext, (@{
                                                       @"default": @(UIUserNotificationActionContextDefault),
                                                       @"minimal": @(UIUserNotificationActionContextMinimal)
                                                       }), UIUserNotificationActionContextDefault, integerValue)
@end

@implementation RCTConvert (UIUserNotificationActionBehavior)
/* iOS 9 only */
RCT_ENUM_CONVERTER(UIUserNotificationActionBehavior, (@{
                                                        @"default": @(UIUserNotificationActionBehaviorDefault),
                                                        @"textInput": @(UIUserNotificationActionBehaviorTextInput)
                                                        }), UIUserNotificationActionBehaviorDefault, integerValue)
@end

47 48 49 50
@implementation RCTConvert (UIMutableUserNotificationAction)
+ (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json
{
    NSDictionary<NSString *, id> *details = [self NSDictionary:json];
Lidan Hifi's avatar
Lidan Hifi committed
51

52
    UIMutableUserNotificationAction* action =[UIMutableUserNotificationAction new];
53 54 55 56 57 58
    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"]];
Lidan Hifi's avatar
Lidan Hifi committed
59

60 61 62
    return action;
}
@end
63

64 65
@implementation RCTConvert (UIMutableUserNotificationCategory)
+ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json
66
{
67 68
    NSDictionary<NSString *, id> *details = [self NSDictionary:json];

69
    UIMutableUserNotificationCategory* category = [UIMutableUserNotificationCategory new];
70 71 72
    category.identifier = details[@"identifier"];

    // category actions
73
    NSMutableArray* actions = [NSMutableArray new];
74 75
    for (NSDictionary* actionJson in [RCTConvert NSArray:details[@"actions"]]) {
        [actions addObject:[RCTConvert UIMutableUserNotificationAction:actionJson]];
76
    }
77 78 79 80

    [category setActions:actions forContext:[RCTConvert UIUserNotificationActionContext:details[@"context"]]];

    return category;
81
}
82 83
@end

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
@implementation RCTConvert (UILocalNotification)
+ (UILocalNotification *)UILocalNotification:(id)json
{
    NSDictionary<NSString *, id> *details = [self NSDictionary:json];

    UILocalNotification* notification = [UILocalNotification new];
    notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]];
    notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
    notification.alertTitle = [RCTConvert NSString:details[@"alertTitle"]];
    notification.alertAction = [RCTConvert NSString:details[@"alertAction"]];
    notification.soundName = [RCTConvert NSString:details[@"soundName"]] ?: UILocalNotificationDefaultSoundName;
    notification.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]] ?: @{};
    notification.category = [RCTConvert NSString:details[@"category"]];

    return notification;
}
@end

102 103 104 105 106
@implementation RNNotifications

RCT_EXPORT_MODULE()

@synthesize bridge = _bridge;
Lidan Hifi's avatar
Lidan Hifi committed
107 108 109 110 111 112 113 114 115

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setBridge:(RCTBridge *)bridge
{
    _bridge = bridge;
Lidan Hifi's avatar
Lidan Hifi committed
116

117 118 119 120 121
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationsRegistered:)
                                                 name:RNNotificationsRegistered
                                               object:nil];

122 123 124 125 126
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationsRegistrationFailed:)
                                                 name:RNNotificationsRegistrationFailed
                                               object:nil];

127 128 129 130 131
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handlePushKitRegistered:)
                                                 name:RNPushKitRegistered
                                               object:nil];

Lidan Hifi's avatar
Lidan Hifi committed
132 133
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationReceivedForeground:)
Lidan Hifi's avatar
Lidan Hifi committed
134
                                                 name:RNNotificationReceivedForeground
Lidan Hifi's avatar
Lidan Hifi committed
135
                                               object:nil];
Lidan Hifi's avatar
Lidan Hifi committed
136

Lidan Hifi's avatar
Lidan Hifi committed
137 138
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationReceivedBackground:)
Lidan Hifi's avatar
Lidan Hifi committed
139
                                                 name:RNNotificationReceivedBackground
Lidan Hifi's avatar
Lidan Hifi committed
140
                                               object:nil];
Lidan Hifi's avatar
Lidan Hifi committed
141

Lidan Hifi's avatar
Lidan Hifi committed
142 143
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationOpened:)
Lidan Hifi's avatar
Lidan Hifi committed
144
                                                 name:RNNotificationOpened
Lidan Hifi's avatar
Lidan Hifi committed
145
                                               object:nil];
146 147 148 149 150

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotificationActionTriggered:)
                                                 name:RNNotificationActionTriggered
                                               object:nil];
151 152 153

    [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    [RNNotificationsBridgeQueue sharedInstance].openedLocalNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
Lidan Hifi's avatar
Lidan Hifi committed
154 155 156
}

/*
157
 * Public Methods
Lidan Hifi's avatar
Lidan Hifi committed
158
 */
159 160 161 162 163 164 165 166 167 168 169 170 171 172
+ (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) {
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
}

+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationsRegistered
                                                        object:self
                                                      userInfo:@{@"deviceToken": [self deviceTokenToString:deviceToken]}];
}

173 174 175 176 177 178
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationsRegistrationFailed
                                                        object:self
                                                      userInfo:@{@"code": [NSNumber numberWithInteger:error.code], @"domain": error.domain, @"localizedDescription": error.localizedDescription}];
}

Lidan Hifi's avatar
Lidan Hifi committed
179 180 181
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
{
    UIApplicationState state = [UIApplication sharedApplication].applicationState;
Lidan Hifi's avatar
Lidan Hifi committed
182

183 184 185 186 187 188 189 190 191 192 193 194 195
    if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) {
        // JS thread is ready, push the notification to the bridge

        if (state == UIApplicationStateActive) {
            // Notification received foreground
            [self didReceiveNotificationOnForegroundState:notification];
        } else if (state == UIApplicationStateInactive) {
            // Notification opened
            [self didNotificationOpen:notification];
        } else {
            // Notification received background
            [self didReceiveNotificationOnBackgroundState:notification];
        }
Lidan Hifi's avatar
Lidan Hifi committed
196
    } else {
197 198
        // JS thread is not ready - store it in the native notifications queue
        [[RNNotificationsBridgeQueue sharedInstance] postNotification:notification];
Lidan Hifi's avatar
Lidan Hifi committed
199 200 201 202 203 204
    }
}

+ (void)didReceiveLocalNotification:(UILocalNotification *)notification
{
    UIApplicationState state = [UIApplication sharedApplication].applicationState;
Lidan Hifi's avatar
Lidan Hifi committed
205

206 207 208 209
    NSMutableDictionary* newUserInfo = notification.userInfo.mutableCopy;
    [newUserInfo removeObjectForKey:@"__id"];
    notification.userInfo = newUserInfo;

210 211 212
    if (state == UIApplicationStateActive) {
        [self didReceiveNotificationOnForegroundState:notification.userInfo];
    } else if (state == UIApplicationStateInactive) {
Lidan Hifi's avatar
Lidan Hifi committed
213 214 215 216 217 218 219 220
        NSString* notificationId = [notification.userInfo objectForKey:@"notificationId"];
        if (notificationId) {
            [self clearNotificationFromNotificationsCenter:notificationId];
        }
        [self didNotificationOpen:notification.userInfo];
    }
}

221
+ (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
222
{
223
    [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:notification.userInfo completionHandler:completionHandler];
224 225
}

226
+ (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
227
{
228
    [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:userInfo completionHandler:completionHandler];
229 230
}

Lidan Hifi's avatar
Lidan Hifi committed
231 232 233 234 235
/*
 * Notification handlers
 */
+ (void)didReceiveNotificationOnForegroundState:(NSDictionary *)notification
{
Lidan Hifi's avatar
Lidan Hifi committed
236
    [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationReceivedForeground
Lidan Hifi's avatar
Lidan Hifi committed
237 238 239 240 241 242
                                                        object:self
                                                      userInfo:notification];
}

+ (void)didReceiveNotificationOnBackgroundState:(NSDictionary *)notification
{
243 244 245 246
    NSDictionary* managedAps  = [notification objectForKey:@"managedAps"];
    NSDictionary* alert = [managedAps objectForKey:@"alert"];
    NSString* action = [managedAps objectForKey:@"action"];
    NSString* notificationId = [managedAps objectForKey:@"notificationId"];
Lidan Hifi's avatar
Lidan Hifi committed
247 248 249

    if (action) {
        // create or delete notification
Lidan Hifi's avatar
Lidan Hifi committed
250
        if ([action isEqualToString: RNNotificationCreateAction]
Lidan Hifi's avatar
Lidan Hifi committed
251 252 253
            && notificationId
            && alert) {
            [self dispatchLocalNotificationFromNotification:notification];
Lidan Hifi's avatar
Lidan Hifi committed
254 255

        } else if ([action isEqualToString: RNNotificationClearAction] && notificationId) {
Lidan Hifi's avatar
Lidan Hifi committed
256 257 258
            [self clearNotificationFromNotificationsCenter:notificationId];
        }
    }
Lidan Hifi's avatar
Lidan Hifi committed
259

260 261 262
    [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationReceivedBackground
                                                        object:self
                                                      userInfo:notification];
Lidan Hifi's avatar
Lidan Hifi committed
263 264 265 266
}

+ (void)didNotificationOpen:(NSDictionary *)notification
{
Lidan Hifi's avatar
Lidan Hifi committed
267
    [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationOpened
Lidan Hifi's avatar
Lidan Hifi committed
268 269 270 271 272 273 274 275 276
                                                        object:self
                                                      userInfo:notification];
}

/*
 * Helper methods
 */
+ (void)dispatchLocalNotificationFromNotification:(NSDictionary *)notification
{
277 278 279 280
    NSDictionary* managedAps  = [notification objectForKey:@"managedAps"];
    NSDictionary* alert = [managedAps objectForKey:@"alert"];
    NSString* action = [managedAps objectForKey:@"action"];
    NSString* notificationId = [managedAps objectForKey:@"notificationId"];
Lidan Hifi's avatar
Lidan Hifi committed
281 282

    if ([action isEqualToString: RNNotificationCreateAction]
Lidan Hifi's avatar
Lidan Hifi committed
283 284
        && notificationId
        && alert) {
Lidan Hifi's avatar
Lidan Hifi committed
285

Lidan Hifi's avatar
Lidan Hifi committed
286
        // trigger new client push notification
287
        UILocalNotification* note = [UILocalNotification new];
Lidan Hifi's avatar
Lidan Hifi committed
288 289
        note.alertTitle = [alert objectForKey:@"title"];
        note.alertBody = [alert objectForKey:@"body"];
290
        note.userInfo = notification;
291
        note.soundName = [managedAps objectForKey:@"sound"];
292
        note.category = [managedAps objectForKey:@"category"];
Lidan Hifi's avatar
Lidan Hifi committed
293

Lidan Hifi's avatar
Lidan Hifi committed
294
        [[UIApplication sharedApplication] presentLocalNotificationNow:note];
Lidan Hifi's avatar
Lidan Hifi committed
295

Lidan Hifi's avatar
Lidan Hifi committed
296 297 298 299 300
        // 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];
Lidan Hifi's avatar
Lidan Hifi committed
301

Lidan Hifi's avatar
Lidan Hifi committed
302 303 304 305 306 307 308 309 310 311
        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];
Lidan Hifi's avatar
Lidan Hifi committed
312

Lidan Hifi's avatar
Lidan Hifi committed
313 314 315
        // delete the notification
        [[UIApplication sharedApplication] cancelLocalNotification:notification];
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:notificationKey];
Lidan Hifi's avatar
Lidan Hifi committed
316

317 318
        NSLog(@"Local notification removed: %@", notificationKey);

Lidan Hifi's avatar
Lidan Hifi committed
319 320 321 322 323 324 325 326 327
        return;
    }
}

+ (NSString *)buildNotificationKeyfromNotification:(NSString *)notificationId
{
    return [NSString stringWithFormat:@"%@.%@", [[NSBundle mainBundle] bundleIdentifier], notificationId];
}

328 329 330 331 332 333 334 335 336 337 338 339
+ (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];
}

340
+ (void)requestPermissionsWithCategories:(NSMutableSet *)categories
341
{
342 343
    UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
    UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:types categories:categories];
344

345
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
346 347
}

348
+ (void)emitNotificationActionForIdentifier:(NSString *)identifier responseInfo:(NSDictionary *)responseInfo userInfo:(NSDictionary *)userInfo  completionHandler:(void (^)())completionHandler
349
{
350 351
    NSString* completionKey = [NSString stringWithFormat:@"%@.%@", identifier, [NSString stringWithFormat:@"%d", (long)[[NSDate date] timeIntervalSince1970]]];
    NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier, @"completionKey": completionKey }];
352 353 354 355 356

    // add text
    NSString* text = [responseInfo objectForKey:UIUserNotificationActionResponseTypedTextKey];
    if (text != NULL) {
        info[@"text"] = text;
357 358
    }

359 360
    // add notification custom data
    if (userInfo != NULL) {
361
        info[@"notification"] = userInfo;
362
    }
363

364 365
    // 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];
366

367 368 369 370 371
    if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) {
        [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered
                                                            object:self
                                                          userInfo:info];
    }
372 373
}

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
+ (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
{
    [[NSNotificationCenter defaultCenter] postNotificationName:RNPushKitRegistered
                                                        object:self
                                                      userInfo:@{@"pushKitToken": [self deviceTokenToString:credentials.token]}];
}

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
{
    [RNNotifications didReceiveRemoteNotification:payload.dictionaryPayload];
}

396 397 398
/*
 * Javascript events
 */
399 400 401 402 403
- (void)handleNotificationsRegistered:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo];
}

404 405 406 407 408
- (void)handleNotificationsRegistrationFailed:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistrationFailed" body:notification.userInfo];
}

409 410 411 412 413
- (void)handlePushKitRegistered:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"pushKitRegistered" body:notification.userInfo];
}

Lidan Hifi's avatar
Lidan Hifi committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
- (void)handleNotificationReceivedForeground:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"notificationReceivedForeground" body:notification.userInfo];
}

- (void)handleNotificationReceivedBackground:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"notificationReceivedBackground" body:notification.userInfo];
}

- (void)handleNotificationOpened:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendDeviceEventWithName:@"notificationOpened" body:notification.userInfo];
}

429 430 431 432 433
- (void)handleNotificationActionTriggered:(NSNotification *)notification
{
    [_bridge.eventDispatcher sendAppEventWithName:@"notificationActionReceived" body:notification.userInfo];
}

Lidan Hifi's avatar
Lidan Hifi committed
434 435 436
/*
 * React Native exported methods
 */
437
RCT_EXPORT_METHOD(requestPermissionsWithCategories:(NSArray *)json)
Lidan Hifi's avatar
Lidan Hifi committed
438
{
439 440 441
    NSMutableSet* categories = nil;

    if ([json count] > 0) {
442
        categories = [NSMutableSet new];
443 444 445 446 447 448
        for (NSDictionary* categoryJson in json) {
            [categories addObject:[RCTConvert UIMutableUserNotificationCategory:categoryJson]];
        }
    }

    [RNNotifications requestPermissionsWithCategories:categories];
Lidan Hifi's avatar
Lidan Hifi committed
449 450
}

451 452 453 454 455
RCT_EXPORT_METHOD(log:(NSString *)message)
{
    NSLog(message);
}

456
RCT_EXPORT_METHOD(completionHandler:(NSString *)completionKey)
457
{
458
    [[RNNotificationsBridgeQueue sharedInstance] completeAction:completionKey];
459 460
}

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
RCT_EXPORT_METHOD(abandonPermissions)
{
    [[UIApplication sharedApplication] unregisterForRemoteNotifications];
}

RCT_EXPORT_METHOD(registerPushKit)
{
    [RNNotifications registerPushKit];
}

RCT_EXPORT_METHOD(backgroundTimeRemaining:(RCTResponseSenderBlock)callback)
{
    NSTimeInterval remainingTime = [UIApplication sharedApplication].backgroundTimeRemaining;
    callback(@[ [NSNumber numberWithDouble:remainingTime] ]);
}

477 478
RCT_EXPORT_METHOD(consumeBackgroundQueue)
{
479 480 481 482
    // Mark JS Thread as ready
    [RNNotificationsBridgeQueue sharedInstance].jsIsReady = YES;

    // Push actions to JS
483 484 485 486 487 488
    [[RNNotificationsBridgeQueue sharedInstance] consumeActionsQueue:^(NSDictionary* action) {
        [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered
                                                            object:self
                                                          userInfo:action];
    }];

489
    // Push background notifications to JS
490
    [[RNNotificationsBridgeQueue sharedInstance] consumeNotificationsQueue:^(NSDictionary* notification) {
491
        [RNNotifications didReceiveRemoteNotification:notification];
492 493
    }];

494 495 496 497 498 499 500 501 502 503 504
    // Push opened local notifications
    NSDictionary* openedLocalNotification = [RNNotificationsBridgeQueue sharedInstance].openedLocalNotification;
    if (openedLocalNotification) {
        [RNNotifications didNotificationOpen:openedLocalNotification];
    }

    // Push opened remote notifications
    NSDictionary* openedRemoteNotification = [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification;
    if (openedRemoteNotification) {
        [RNNotifications didNotificationOpen:openedRemoteNotification];
    }
505 506
}

507
RCT_EXPORT_METHOD(localNotification:(NSDictionary *)notification withId:(NSString *)notificationId)
508
{
509 510 511 512 513
    UILocalNotification* localNotification = [RCTConvert UILocalNotification:notification];
    NSMutableArray* userInfo = localNotification.userInfo.mutableCopy;
    [userInfo setValue:notificationId forKey:@"__id"];
    localNotification.userInfo = userInfo;

514
    if ([notification objectForKey:@"fireDate"] != nil) {
515
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
516
    } else {
517
        [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
518 519 520
    }
}

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
RCT_EXPORT_METHOD(cancelLocalNotification:(NSString *)notificationId)
{
    for (UILocalNotification* notification in [UIApplication sharedApplication].scheduledLocalNotifications) {
        NSDictionary* notificationInfo = notification.userInfo;

        if ([[notificationInfo objectForKey:@"__id"] isEqualToString:notificationId]) {
            [[UIApplication sharedApplication] cancelLocalNotification:notification];
        }
    }
}

RCT_EXPORT_METHOD(cancelAllLocalNotifications)
{
    [RCTSharedApplication() cancelAllLocalNotifications];
}

Lidan Hifi's avatar
Lidan Hifi committed
537
@end