react-native-notify-kit 10.1.0 → 10.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -96
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
- package/android/src/main/java/app/notifee/core/NotificationManager.java +21 -8
- package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
- package/android/src/main/java/app/notifee/core/ReceiverService.java +18 -13
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidActionModel.java +1 -2
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidPressActionModel.java +3 -9
- package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
- package/android/src/main/java/app/notifee/core/utility/IntentUtils.java +0 -28
- package/android/src/main/java/app/notifee/core/utility/PowerManagerUtils.java +79 -41
- package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +5 -1
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeReactUtils.kt +1 -2
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +150 -0
- package/cli/dist/lib/patchPodfile.d.ts +3 -1
- package/cli/dist/lib/patchPodfile.js +125 -33
- package/cli/dist/lib/patchPodfile.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/types/Module.d.ts +27 -13
- package/dist/types/Notification.d.ts +1 -1
- package/dist/types/NotificationIOS.d.ts +44 -21
- package/dist/types/NotificationIOS.js +15 -1
- package/dist/types/NotificationIOS.js.map +1 -1
- package/dist/types/PowerManagerInfo.d.ts +9 -4
- package/dist/types/Trigger.d.ts +45 -2
- package/dist/types/Trigger.js +22 -0
- package/dist/types/Trigger.js.map +1 -1
- package/dist/validators/validateIOSCategory.js +2 -2
- package/dist/validators/validateIOSCategory.js.map +1 -1
- package/dist/validators/validateTrigger.js +26 -1
- package/dist/validators/validateTrigger.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +20 -10
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +1 -2
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +44 -35
- package/ios/NotifeeCore/NotifeeCore.m +1042 -119
- package/ios/NotifeeCore/NotifeeCoreUtil.h +36 -1
- package/ios/NotifeeCore/NotifeeCoreUtil.m +533 -9
- package/ios/RNNotifee/NotifeeApiModule.mm +2 -2
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/types/Module.ts +27 -13
- package/src/types/Notification.ts +1 -1
- package/src/types/NotificationIOS.ts +43 -28
- package/src/types/PowerManagerInfo.ts +9 -4
- package/src/types/Trigger.ts +45 -1
- package/src/validators/validateIOSCategory.ts +4 -2
- package/src/validators/validateTrigger.ts +38 -0
- package/src/version.ts +1 -1
|
@@ -39,9 +39,11 @@ typedef NS_ENUM(NSInteger, NotifeeCoreTriggerType) {
|
|
|
39
39
|
|
|
40
40
|
// Enum representing repeat frequency for TimestampTrigger
|
|
41
41
|
typedef NS_ENUM(NSInteger, NotifeeCoreRepeatFrequency) {
|
|
42
|
+
NotifeeCoreRepeatFrequencyNone = -1,
|
|
42
43
|
NotifeeCoreRepeatFrequencyHourly = 0,
|
|
43
44
|
NotifeeCoreRepeatFrequencyDaily = 1,
|
|
44
|
-
NotifeeCoreRepeatFrequencyWeekly = 2
|
|
45
|
+
NotifeeCoreRepeatFrequencyWeekly = 2,
|
|
46
|
+
NotifeeCoreRepeatFrequencyMonthly = 3
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
@interface NotifeeCoreUtil : NSObject
|
|
@@ -65,6 +67,39 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRepeatFrequency) {
|
|
|
65
67
|
|
|
66
68
|
+ (UNNotificationTrigger *)triggerFromDictionary:(NSDictionary *)triggerDict;
|
|
67
69
|
|
|
70
|
+
+ (BOOL)isRollingTimestampTrigger:(nullable NSDictionary *)triggerDict;
|
|
71
|
+
|
|
72
|
+
+ (NSArray<NSNumber *> *)rollingTimestampOccurrencesFromTrigger:(nullable NSDictionary *)triggerDict
|
|
73
|
+
nowMs:(nullable NSNumber *)nowMs
|
|
74
|
+
maxCount:(NSInteger)maxCount;
|
|
75
|
+
|
|
76
|
+
+ (nullable NSString *)rollingInternalNotificationIdForPublicId:(nullable NSString *)publicId
|
|
77
|
+
occurrenceMs:(nullable NSNumber *)occurrenceMs;
|
|
78
|
+
|
|
79
|
+
+ (nullable NSString *)rollingPublicIdFromInternalNotificationId:(nullable NSString *)internalId;
|
|
80
|
+
|
|
81
|
+
+ (nullable NSNumber *)rollingOccurrenceMsFromInternalNotificationId:
|
|
82
|
+
(nullable NSString *)internalId;
|
|
83
|
+
|
|
84
|
+
+ (BOOL)isRollingInternalNotificationId:(nullable NSString *)notificationId;
|
|
85
|
+
|
|
86
|
+
+ (NSInteger)rollingPendingBudget;
|
|
87
|
+
|
|
88
|
+
+ (NSInteger)rollingTargetPerTrigger;
|
|
89
|
+
|
|
90
|
+
+ (NSMutableDictionary *)getRollingTimestampTriggers;
|
|
91
|
+
|
|
92
|
+
+ (void)setRollingTimestampTriggers:(nullable NSDictionary *)records;
|
|
93
|
+
|
|
94
|
+
+ (void)upsertRollingTimestampTriggerRecord:(nullable NSDictionary *)record
|
|
95
|
+
publicId:(nullable NSString *)publicId;
|
|
96
|
+
|
|
97
|
+
+ (void)removeRollingTimestampTriggerRecordForPublicId:(nullable NSString *)publicId;
|
|
98
|
+
|
|
99
|
+
+ (void)clearRollingTimestampTriggerRecords;
|
|
100
|
+
|
|
101
|
+
+ (nullable NSNumber *)rollingLastScheduledOccurrenceMsForRecord:(nullable NSDictionary *)record;
|
|
102
|
+
|
|
68
103
|
+ (NSNumber *)convertToTimestamp:(NSDate *)date;
|
|
69
104
|
|
|
70
105
|
+ (NSDictionary *)parseUNNotificationRequest:(UNNotificationRequest *)request;
|
|
@@ -19,8 +19,39 @@
|
|
|
19
19
|
#include <CoreGraphics/CGGeometry.h>
|
|
20
20
|
#import <Intents/INIntentIdentifiers.h>
|
|
21
21
|
#import <UIKit/UIKit.h>
|
|
22
|
+
#include <limits.h>
|
|
23
|
+
#include <math.h>
|
|
22
24
|
#import "NotifeeCore+NSURLSession.h"
|
|
23
25
|
|
|
26
|
+
static NSString *const kNotifeeRollingTimestampTriggersStorageKey =
|
|
27
|
+
@"app.notifee.core.rollingTimestampTriggers.v1";
|
|
28
|
+
static NSString *const kNotifeeRollingInternalIdPrefix = @"__notifee_rolling__";
|
|
29
|
+
static NSString *const kNotifeeRollingInternalIdSeparator = @"__";
|
|
30
|
+
static NSInteger const kNotifeeRollingPendingBudget = 60;
|
|
31
|
+
static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
|
|
32
|
+
|
|
33
|
+
@interface NotifeeCoreUtil ()
|
|
34
|
+
|
|
35
|
+
+ (nullable NSNumber *)rollingIntegerNumberFromObject:(nullable id)value
|
|
36
|
+
allowNegative:(BOOL)allowNegative
|
|
37
|
+
allowZero:(BOOL)allowZero;
|
|
38
|
+
+ (BOOL)isSupportedRollingRepeatFrequency:(NSInteger)repeatFrequency;
|
|
39
|
+
+ (NSInteger)rollingRepeatIntervalFromTrigger:(NSDictionary *)triggerDict;
|
|
40
|
+
+ (nullable NSDate *)rollingDateByAddingRepeatFrequency:(NSInteger)repeatFrequency
|
|
41
|
+
interval:(NSInteger)interval
|
|
42
|
+
toDate:(NSDate *)date;
|
|
43
|
+
+ (nullable NSDictionary *)rollingPartsFromInternalNotificationId:(nullable NSString *)internalId;
|
|
44
|
+
+ (nullable NSMutableDictionary *)
|
|
45
|
+
rollingSanitizedTimestampTriggerRecord:(nullable NSDictionary *)record
|
|
46
|
+
publicId:(nullable NSString *)publicId
|
|
47
|
+
defaultMissingCreatedAt:(BOOL)defaultMissingCreatedAt;
|
|
48
|
+
+ (NSMutableDictionary *)rollingSanitizedTimestampTriggerRecords:(nullable NSDictionary *)records
|
|
49
|
+
defaultMissingCreatedAt:(BOOL)defaultMissingCreatedAt;
|
|
50
|
+
+ (nullable id)rollingJSONObjectFromObject:(nullable id)object;
|
|
51
|
+
+ (NSNumber *)rollingCurrentTimestampMs;
|
|
52
|
+
|
|
53
|
+
@end
|
|
54
|
+
|
|
24
55
|
@implementation NotifeeCoreUtil
|
|
25
56
|
|
|
26
57
|
+ (NSNumber *)numberForUNNotificationSetting:(UNNotificationSetting)setting {
|
|
@@ -319,6 +350,499 @@
|
|
|
319
350
|
return trigger;
|
|
320
351
|
}
|
|
321
352
|
|
|
353
|
+
+ (BOOL)isRollingTimestampTrigger:(NSDictionary *)triggerDict {
|
|
354
|
+
if (![triggerDict isKindOfClass:NSDictionary.class]) {
|
|
355
|
+
return NO;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
NSNumber *triggerType = [self rollingIntegerNumberFromObject:triggerDict[@"type"]
|
|
359
|
+
allowNegative:NO
|
|
360
|
+
allowZero:YES];
|
|
361
|
+
if (triggerType == nil || [triggerType integerValue] != NotifeeCoreTriggerTypeTimestamp) {
|
|
362
|
+
return NO;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
NSNumber *timestamp = [self rollingIntegerNumberFromObject:triggerDict[@"timestamp"]
|
|
366
|
+
allowNegative:NO
|
|
367
|
+
allowZero:NO];
|
|
368
|
+
if (timestamp == nil) {
|
|
369
|
+
return NO;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (triggerDict[@"repeatFrequency"] == nil) {
|
|
373
|
+
return NO;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
NSNumber *repeatFrequencyNumber =
|
|
377
|
+
[self rollingIntegerNumberFromObject:triggerDict[@"repeatFrequency"]
|
|
378
|
+
allowNegative:YES
|
|
379
|
+
allowZero:YES];
|
|
380
|
+
if (repeatFrequencyNumber == nil) {
|
|
381
|
+
return NO;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
NSInteger repeatFrequency = [repeatFrequencyNumber integerValue];
|
|
385
|
+
if (repeatFrequency == NotifeeCoreRepeatFrequencyNone ||
|
|
386
|
+
![self isSupportedRollingRepeatFrequency:repeatFrequency]) {
|
|
387
|
+
return NO;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (triggerDict[@"repeatInterval"] != nil) {
|
|
391
|
+
NSNumber *repeatInterval = [self rollingIntegerNumberFromObject:triggerDict[@"repeatInterval"]
|
|
392
|
+
allowNegative:NO
|
|
393
|
+
allowZero:NO];
|
|
394
|
+
if (repeatInterval == nil || [repeatInterval doubleValue] > NSIntegerMax) {
|
|
395
|
+
return NO;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return YES;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
+ (NSArray<NSNumber *> *)rollingTimestampOccurrencesFromTrigger:(NSDictionary *)triggerDict
|
|
403
|
+
nowMs:(NSNumber *)nowMs
|
|
404
|
+
maxCount:(NSInteger)maxCount {
|
|
405
|
+
if (maxCount <= 0 || ![triggerDict isKindOfClass:NSDictionary.class]) {
|
|
406
|
+
return @[];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
NSNumber *triggerType = [self rollingIntegerNumberFromObject:triggerDict[@"type"]
|
|
410
|
+
allowNegative:NO
|
|
411
|
+
allowZero:YES];
|
|
412
|
+
if (triggerType == nil || [triggerType integerValue] != NotifeeCoreTriggerTypeTimestamp) {
|
|
413
|
+
return @[];
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
NSNumber *timestampNumber = [self rollingIntegerNumberFromObject:triggerDict[@"timestamp"]
|
|
417
|
+
allowNegative:NO
|
|
418
|
+
allowZero:NO];
|
|
419
|
+
NSNumber *nowNumber = [self rollingIntegerNumberFromObject:nowMs allowNegative:NO allowZero:YES];
|
|
420
|
+
NSNumber *repeatFrequencyNumber =
|
|
421
|
+
[self rollingIntegerNumberFromObject:triggerDict[@"repeatFrequency"]
|
|
422
|
+
allowNegative:YES
|
|
423
|
+
allowZero:YES];
|
|
424
|
+
if (timestampNumber == nil || nowNumber == nil || repeatFrequencyNumber == nil) {
|
|
425
|
+
return @[];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
NSInteger repeatFrequency = [repeatFrequencyNumber integerValue];
|
|
429
|
+
if (repeatFrequency == NotifeeCoreRepeatFrequencyNone ||
|
|
430
|
+
![self isSupportedRollingRepeatFrequency:repeatFrequency]) {
|
|
431
|
+
return @[];
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
NSInteger repeatInterval = [self rollingRepeatIntervalFromTrigger:triggerDict];
|
|
435
|
+
long long nowMsValue = [nowNumber longLongValue];
|
|
436
|
+
NSDate *candidateDate =
|
|
437
|
+
[NSDate dateWithTimeIntervalSince1970:([timestampNumber doubleValue] / 1000.0)];
|
|
438
|
+
NSMutableArray<NSNumber *> *occurrences = [NSMutableArray array];
|
|
439
|
+
|
|
440
|
+
while (candidateDate != nil &&
|
|
441
|
+
(long long)llround([candidateDate timeIntervalSince1970] * 1000.0) <= nowMsValue) {
|
|
442
|
+
NSDate *nextDate = [self rollingDateByAddingRepeatFrequency:repeatFrequency
|
|
443
|
+
interval:repeatInterval
|
|
444
|
+
toDate:candidateDate];
|
|
445
|
+
if (nextDate == nil || [nextDate timeIntervalSinceDate:candidateDate] <= 0) {
|
|
446
|
+
return @[];
|
|
447
|
+
}
|
|
448
|
+
candidateDate = nextDate;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
while (candidateDate != nil && [occurrences count] < (NSUInteger)maxCount) {
|
|
452
|
+
long long occurrenceMs = (long long)llround([candidateDate timeIntervalSince1970] * 1000.0);
|
|
453
|
+
if (occurrenceMs > nowMsValue) {
|
|
454
|
+
[occurrences addObject:@(occurrenceMs)];
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
NSDate *nextDate = [self rollingDateByAddingRepeatFrequency:repeatFrequency
|
|
458
|
+
interval:repeatInterval
|
|
459
|
+
toDate:candidateDate];
|
|
460
|
+
if (nextDate == nil || [nextDate timeIntervalSinceDate:candidateDate] <= 0) {
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
candidateDate = nextDate;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return occurrences;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
+ (NSString *)rollingInternalNotificationIdForPublicId:(NSString *)publicId
|
|
470
|
+
occurrenceMs:(NSNumber *)occurrenceMs {
|
|
471
|
+
if (![publicId isKindOfClass:NSString.class] || [publicId length] == 0) {
|
|
472
|
+
return nil;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
NSNumber *occurrenceNumber = [self rollingIntegerNumberFromObject:occurrenceMs
|
|
476
|
+
allowNegative:NO
|
|
477
|
+
allowZero:NO];
|
|
478
|
+
if (occurrenceNumber == nil) {
|
|
479
|
+
return nil;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
NSMutableCharacterSet *allowedCharacters =
|
|
483
|
+
[NSMutableCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
484
|
+
@"abcdefghijklmnopqrstuvwxyz"
|
|
485
|
+
@"0123456789-._~"];
|
|
486
|
+
NSString *escapedPublicId =
|
|
487
|
+
[publicId stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
|
|
488
|
+
if (escapedPublicId == nil || [escapedPublicId length] == 0) {
|
|
489
|
+
return nil;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return [NSString stringWithFormat:@"%@%@%@%lld", kNotifeeRollingInternalIdPrefix, escapedPublicId,
|
|
493
|
+
kNotifeeRollingInternalIdSeparator,
|
|
494
|
+
[occurrenceNumber longLongValue]];
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
+ (NSString *)rollingPublicIdFromInternalNotificationId:(NSString *)internalId {
|
|
498
|
+
NSDictionary *parts = [self rollingPartsFromInternalNotificationId:internalId];
|
|
499
|
+
return parts[@"publicId"];
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
+ (NSNumber *)rollingOccurrenceMsFromInternalNotificationId:(NSString *)internalId {
|
|
503
|
+
NSDictionary *parts = [self rollingPartsFromInternalNotificationId:internalId];
|
|
504
|
+
return parts[@"occurrenceMs"];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
+ (BOOL)isRollingInternalNotificationId:(NSString *)notificationId {
|
|
508
|
+
return [self rollingPartsFromInternalNotificationId:notificationId] != nil;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
+ (NSInteger)rollingPendingBudget {
|
|
512
|
+
return kNotifeeRollingPendingBudget;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
+ (NSInteger)rollingTargetPerTrigger {
|
|
516
|
+
return kNotifeeRollingTargetPerTrigger;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
+ (NSMutableDictionary *)getRollingTimestampTriggers {
|
|
520
|
+
id storedRecords = [[NSUserDefaults standardUserDefaults]
|
|
521
|
+
objectForKey:kNotifeeRollingTimestampTriggersStorageKey];
|
|
522
|
+
NSDictionary *records = nil;
|
|
523
|
+
|
|
524
|
+
if ([storedRecords isKindOfClass:NSData.class]) {
|
|
525
|
+
NSError *error = nil;
|
|
526
|
+
id jsonObject = [NSJSONSerialization JSONObjectWithData:storedRecords options:0 error:&error];
|
|
527
|
+
if (error != nil || ![jsonObject isKindOfClass:NSDictionary.class]) {
|
|
528
|
+
return [NSMutableDictionary dictionary];
|
|
529
|
+
}
|
|
530
|
+
records = jsonObject;
|
|
531
|
+
} else if ([storedRecords isKindOfClass:NSDictionary.class]) {
|
|
532
|
+
records = storedRecords;
|
|
533
|
+
} else {
|
|
534
|
+
return [NSMutableDictionary dictionary];
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return [self rollingSanitizedTimestampTriggerRecords:records defaultMissingCreatedAt:YES];
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
+ (void)setRollingTimestampTriggers:(NSDictionary *)records {
|
|
541
|
+
NSMutableDictionary *sanitizedRecords = [self rollingSanitizedTimestampTriggerRecords:records
|
|
542
|
+
defaultMissingCreatedAt:YES];
|
|
543
|
+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
544
|
+
|
|
545
|
+
if ([sanitizedRecords count] == 0) {
|
|
546
|
+
[defaults removeObjectForKey:kNotifeeRollingTimestampTriggersStorageKey];
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
NSError *error = nil;
|
|
551
|
+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sanitizedRecords
|
|
552
|
+
options:0
|
|
553
|
+
error:&error];
|
|
554
|
+
if (error != nil || jsonData == nil) {
|
|
555
|
+
[defaults removeObjectForKey:kNotifeeRollingTimestampTriggersStorageKey];
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
[defaults setObject:jsonData forKey:kNotifeeRollingTimestampTriggersStorageKey];
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
+ (void)upsertRollingTimestampTriggerRecord:(NSDictionary *)record publicId:(NSString *)publicId {
|
|
563
|
+
NSMutableDictionary *sanitizedRecord = [self rollingSanitizedTimestampTriggerRecord:record
|
|
564
|
+
publicId:publicId
|
|
565
|
+
defaultMissingCreatedAt:YES];
|
|
566
|
+
if (sanitizedRecord == nil) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
NSMutableDictionary *records = [self getRollingTimestampTriggers];
|
|
571
|
+
records[sanitizedRecord[@"publicId"]] = sanitizedRecord;
|
|
572
|
+
[self setRollingTimestampTriggers:records];
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
+ (void)removeRollingTimestampTriggerRecordForPublicId:(NSString *)publicId {
|
|
576
|
+
if (![publicId isKindOfClass:NSString.class] || [publicId length] == 0) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
NSMutableDictionary *records = [self getRollingTimestampTriggers];
|
|
581
|
+
[records removeObjectForKey:publicId];
|
|
582
|
+
[self setRollingTimestampTriggers:records];
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
+ (void)clearRollingTimestampTriggerRecords {
|
|
586
|
+
[[NSUserDefaults standardUserDefaults]
|
|
587
|
+
removeObjectForKey:kNotifeeRollingTimestampTriggersStorageKey];
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
+ (NSNumber *)rollingLastScheduledOccurrenceMsForRecord:(NSDictionary *)record {
|
|
591
|
+
if (![record isKindOfClass:NSDictionary.class]) {
|
|
592
|
+
return nil;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
NSNumber *lastScheduledOccurrence =
|
|
596
|
+
[self rollingIntegerNumberFromObject:record[@"lastScheduledOccurrenceMs"]
|
|
597
|
+
allowNegative:NO
|
|
598
|
+
allowZero:NO];
|
|
599
|
+
if (lastScheduledOccurrence != nil) {
|
|
600
|
+
return lastScheduledOccurrence;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
NSDictionary *trigger = record[@"trigger"];
|
|
604
|
+
if (![trigger isKindOfClass:NSDictionary.class]) {
|
|
605
|
+
return nil;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return [self rollingIntegerNumberFromObject:trigger[@"timestamp"] allowNegative:NO allowZero:NO];
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
+ (NSNumber *)rollingIntegerNumberFromObject:(id)value
|
|
612
|
+
allowNegative:(BOOL)allowNegative
|
|
613
|
+
allowZero:(BOOL)allowZero {
|
|
614
|
+
if (![value isKindOfClass:NSNumber.class] ||
|
|
615
|
+
CFGetTypeID((__bridge CFTypeRef)value) == CFBooleanGetTypeID()) {
|
|
616
|
+
return nil;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
double number = [value doubleValue];
|
|
620
|
+
if (!isfinite(number) || floor(number) != number || number > LLONG_MAX || number < LLONG_MIN) {
|
|
621
|
+
return nil;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
if (!allowNegative && number < 0) {
|
|
625
|
+
return nil;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (!allowZero && number == 0) {
|
|
629
|
+
return nil;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
return @((long long)number);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
+ (BOOL)isSupportedRollingRepeatFrequency:(NSInteger)repeatFrequency {
|
|
636
|
+
return repeatFrequency == NotifeeCoreRepeatFrequencyHourly ||
|
|
637
|
+
repeatFrequency == NotifeeCoreRepeatFrequencyDaily ||
|
|
638
|
+
repeatFrequency == NotifeeCoreRepeatFrequencyWeekly ||
|
|
639
|
+
repeatFrequency == NotifeeCoreRepeatFrequencyMonthly;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
+ (NSInteger)rollingRepeatIntervalFromTrigger:(NSDictionary *)triggerDict {
|
|
643
|
+
NSNumber *repeatInterval = [self rollingIntegerNumberFromObject:triggerDict[@"repeatInterval"]
|
|
644
|
+
allowNegative:NO
|
|
645
|
+
allowZero:NO];
|
|
646
|
+
if (repeatInterval == nil || [repeatInterval doubleValue] > NSIntegerMax) {
|
|
647
|
+
return 1;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return [repeatInterval integerValue];
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
+ (NSDate *)rollingDateByAddingRepeatFrequency:(NSInteger)repeatFrequency
|
|
654
|
+
interval:(NSInteger)interval
|
|
655
|
+
toDate:(NSDate *)date {
|
|
656
|
+
NSDateComponents *components = [[NSDateComponents alloc] init];
|
|
657
|
+
|
|
658
|
+
if (repeatFrequency == NotifeeCoreRepeatFrequencyHourly) {
|
|
659
|
+
components.hour = interval;
|
|
660
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyDaily) {
|
|
661
|
+
components.day = interval;
|
|
662
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyWeekly) {
|
|
663
|
+
components.weekOfYear = interval;
|
|
664
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyMonthly) {
|
|
665
|
+
components.month = interval;
|
|
666
|
+
} else {
|
|
667
|
+
return nil;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
return [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:date options:0];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
+ (NSDictionary *)rollingPartsFromInternalNotificationId:(NSString *)internalId {
|
|
674
|
+
if (![internalId isKindOfClass:NSString.class] ||
|
|
675
|
+
![internalId hasPrefix:kNotifeeRollingInternalIdPrefix]) {
|
|
676
|
+
return nil;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
NSString *suffix = [internalId substringFromIndex:[kNotifeeRollingInternalIdPrefix length]];
|
|
680
|
+
NSRange separatorRange = [suffix rangeOfString:kNotifeeRollingInternalIdSeparator
|
|
681
|
+
options:NSBackwardsSearch];
|
|
682
|
+
if (separatorRange.location == NSNotFound || separatorRange.location == 0) {
|
|
683
|
+
return nil;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
NSString *escapedPublicId = [suffix substringToIndex:separatorRange.location];
|
|
687
|
+
NSString *occurrenceString = [suffix substringFromIndex:NSMaxRange(separatorRange)];
|
|
688
|
+
if ([escapedPublicId length] == 0 || [occurrenceString length] == 0) {
|
|
689
|
+
return nil;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
|
|
693
|
+
if ([occurrenceString rangeOfCharacterFromSet:nonDigits].location != NSNotFound) {
|
|
694
|
+
return nil;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
long long occurrenceMs = [occurrenceString longLongValue];
|
|
698
|
+
if (occurrenceMs <= 0 ||
|
|
699
|
+
![[NSString stringWithFormat:@"%lld", occurrenceMs] isEqualToString:occurrenceString]) {
|
|
700
|
+
return nil;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
NSString *publicId = [escapedPublicId stringByRemovingPercentEncoding];
|
|
704
|
+
if (![publicId isKindOfClass:NSString.class] || [publicId length] == 0) {
|
|
705
|
+
return nil;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return @{@"publicId" : publicId, @"occurrenceMs" : @(occurrenceMs)};
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
+ (NSMutableDictionary *)rollingSanitizedTimestampTriggerRecord:(NSDictionary *)record
|
|
712
|
+
publicId:(NSString *)publicId
|
|
713
|
+
defaultMissingCreatedAt:(BOOL)defaultMissingCreatedAt {
|
|
714
|
+
if (![record isKindOfClass:NSDictionary.class]) {
|
|
715
|
+
return nil;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
NSString *resolvedPublicId = publicId;
|
|
719
|
+
if (![resolvedPublicId isKindOfClass:NSString.class] || [resolvedPublicId length] == 0) {
|
|
720
|
+
resolvedPublicId = record[@"publicId"];
|
|
721
|
+
}
|
|
722
|
+
if (![resolvedPublicId isKindOfClass:NSString.class] || [resolvedPublicId length] == 0) {
|
|
723
|
+
return nil;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
id notification = [self rollingJSONObjectFromObject:record[@"notification"]];
|
|
727
|
+
id trigger = [self rollingJSONObjectFromObject:record[@"trigger"]];
|
|
728
|
+
if (![notification isKindOfClass:NSDictionary.class] ||
|
|
729
|
+
![trigger isKindOfClass:NSDictionary.class]) {
|
|
730
|
+
return nil;
|
|
731
|
+
}
|
|
732
|
+
if (![self isRollingTimestampTrigger:trigger]) {
|
|
733
|
+
return nil;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
NSMutableDictionary *sanitizedRecord = [NSMutableDictionary dictionary];
|
|
737
|
+
sanitizedRecord[@"publicId"] = resolvedPublicId;
|
|
738
|
+
sanitizedRecord[@"notification"] = notification;
|
|
739
|
+
sanitizedRecord[@"trigger"] = trigger;
|
|
740
|
+
|
|
741
|
+
NSNumber *lastScheduledOccurrence =
|
|
742
|
+
[self rollingIntegerNumberFromObject:record[@"lastScheduledOccurrenceMs"]
|
|
743
|
+
allowNegative:NO
|
|
744
|
+
allowZero:NO];
|
|
745
|
+
if (lastScheduledOccurrence != nil) {
|
|
746
|
+
sanitizedRecord[@"lastScheduledOccurrenceMs"] = lastScheduledOccurrence;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
NSMutableArray<NSString *> *scheduledIds = [NSMutableArray array];
|
|
750
|
+
NSArray *rawScheduledIds = record[@"scheduledIds"];
|
|
751
|
+
if ([rawScheduledIds isKindOfClass:NSArray.class]) {
|
|
752
|
+
for (id scheduledId in rawScheduledIds) {
|
|
753
|
+
if ([scheduledId isKindOfClass:NSString.class] && [scheduledId length] > 0) {
|
|
754
|
+
[scheduledIds addObject:scheduledId];
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
sanitizedRecord[@"scheduledIds"] = scheduledIds;
|
|
759
|
+
|
|
760
|
+
NSNumber *createdAt = [self rollingIntegerNumberFromObject:record[@"createdAtMs"]
|
|
761
|
+
allowNegative:NO
|
|
762
|
+
allowZero:NO];
|
|
763
|
+
if (createdAt != nil) {
|
|
764
|
+
sanitizedRecord[@"createdAtMs"] = createdAt;
|
|
765
|
+
} else if (defaultMissingCreatedAt) {
|
|
766
|
+
sanitizedRecord[@"createdAtMs"] = [self rollingCurrentTimestampMs];
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
return sanitizedRecord;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
+ (NSMutableDictionary *)rollingSanitizedTimestampTriggerRecords:(NSDictionary *)records
|
|
773
|
+
defaultMissingCreatedAt:(BOOL)defaultMissingCreatedAt {
|
|
774
|
+
NSMutableDictionary *sanitizedRecords = [NSMutableDictionary dictionary];
|
|
775
|
+
if (![records isKindOfClass:NSDictionary.class]) {
|
|
776
|
+
return sanitizedRecords;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
for (id key in records) {
|
|
780
|
+
if (![key isKindOfClass:NSString.class] || [key length] == 0) {
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
NSMutableDictionary *record =
|
|
785
|
+
[self rollingSanitizedTimestampTriggerRecord:records[key]
|
|
786
|
+
publicId:key
|
|
787
|
+
defaultMissingCreatedAt:defaultMissingCreatedAt];
|
|
788
|
+
if (record != nil) {
|
|
789
|
+
sanitizedRecords[key] = record;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return sanitizedRecords;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
+ (id)rollingJSONObjectFromObject:(id)object {
|
|
797
|
+
if (object == nil || object == [NSNull null]) {
|
|
798
|
+
return [NSNull null];
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if ([object isKindOfClass:NSString.class]) {
|
|
802
|
+
return object;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
if ([object isKindOfClass:NSNumber.class]) {
|
|
806
|
+
double number = [object doubleValue];
|
|
807
|
+
if (!isfinite(number)) {
|
|
808
|
+
return nil;
|
|
809
|
+
}
|
|
810
|
+
return object;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if ([object isKindOfClass:NSArray.class]) {
|
|
814
|
+
NSMutableArray *array = [NSMutableArray array];
|
|
815
|
+
for (id value in (NSArray *)object) {
|
|
816
|
+
id sanitizedValue = [self rollingJSONObjectFromObject:value];
|
|
817
|
+
if (sanitizedValue != nil) {
|
|
818
|
+
[array addObject:sanitizedValue];
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
return array;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if ([object isKindOfClass:NSDictionary.class]) {
|
|
825
|
+
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
|
826
|
+
for (id key in (NSDictionary *)object) {
|
|
827
|
+
if (![key isKindOfClass:NSString.class]) {
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
id sanitizedValue = [self rollingJSONObjectFromObject:((NSDictionary *)object)[key]];
|
|
832
|
+
if (sanitizedValue != nil) {
|
|
833
|
+
dictionary[key] = sanitizedValue;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return dictionary;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
return nil;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
+ (NSNumber *)rollingCurrentTimestampMs {
|
|
843
|
+
return @((long long)llround([[NSDate date] timeIntervalSince1970] * 1000.0));
|
|
844
|
+
}
|
|
845
|
+
|
|
322
846
|
/**
|
|
323
847
|
* Returns an UNNotificationTrigger from NSDictionary representing a
|
|
324
848
|
* TimestampTrigger
|
|
@@ -408,12 +932,9 @@
|
|
|
408
932
|
NSMutableArray<NSNumber *> *intentIdentifiers = [[NSMutableArray alloc] init];
|
|
409
933
|
|
|
410
934
|
for (NSString *identifier in identifiers) {
|
|
411
|
-
if ([identifier isEqualToString:
|
|
412
|
-
// IOSIntentIdentifier.
|
|
413
|
-
[intentIdentifiers addObject:@
|
|
414
|
-
} else if ([identifier isEqualToString:INStartVideoCallIntentIdentifier]) {
|
|
415
|
-
// IOSIntentIdentifier.START_VIDEO_CALL
|
|
416
|
-
[intentIdentifiers addObject:@1];
|
|
935
|
+
if ([identifier isEqualToString:INStartCallIntentIdentifier]) {
|
|
936
|
+
// IOSIntentIdentifier.START_CALL
|
|
937
|
+
[intentIdentifiers addObject:@25];
|
|
417
938
|
} else if ([identifier isEqualToString:INSearchCallHistoryIntentIdentifier]) {
|
|
418
939
|
// IOSIntentIdentifier.SEARCH_CALL_HISTORY
|
|
419
940
|
[intentIdentifiers addObject:@2];
|
|
@@ -494,12 +1015,15 @@
|
|
|
494
1015
|
NSMutableArray<NSString *> *intentIdentifiers = [[NSMutableArray alloc] init];
|
|
495
1016
|
|
|
496
1017
|
for (NSNumber *identifier in identifiers) {
|
|
497
|
-
if ([identifier isEqualToNumber:@
|
|
1018
|
+
if ([identifier isEqualToNumber:@25]) {
|
|
1019
|
+
// IOSIntentIdentifier.START_CALL
|
|
1020
|
+
[intentIdentifiers addObject:INStartCallIntentIdentifier];
|
|
1021
|
+
} else if ([identifier isEqualToNumber:@0]) {
|
|
498
1022
|
// IOSIntentIdentifier.START_AUDIO_CALL
|
|
499
|
-
[intentIdentifiers addObject:
|
|
1023
|
+
[intentIdentifiers addObject:INStartCallIntentIdentifier];
|
|
500
1024
|
} else if ([identifier isEqualToNumber:@1]) {
|
|
501
1025
|
// IOSIntentIdentifier.START_VIDEO_CALL
|
|
502
|
-
[intentIdentifiers addObject:
|
|
1026
|
+
[intentIdentifiers addObject:INStartCallIntentIdentifier];
|
|
503
1027
|
} else if ([identifier isEqualToNumber:@2]) {
|
|
504
1028
|
// IOSIntentIdentifier.SEARCH_CALL_HISTORY
|
|
505
1029
|
[intentIdentifiers addObject:INSearchCallHistoryIntentIdentifier];
|
|
@@ -104,8 +104,8 @@ RCT_EXPORT_MODULE();
|
|
|
104
104
|
- (void)sendNotifeeCoreEvent:(NSDictionary *_Nonnull)eventBody {
|
|
105
105
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
106
106
|
@synchronized(self) {
|
|
107
|
-
if (!hasListeners) {
|
|
108
|
-
[pendingCoreEvents addObject:eventBody];
|
|
107
|
+
if (!self->hasListeners) {
|
|
108
|
+
[self->pendingCoreEvents addObject:eventBody];
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -33,3 +33,5 @@ export * from './types/NotificationIOS';
|
|
|
33
33
|
export * from './types/NotificationAndroid';
|
|
34
34
|
export * from './types/PowerManagerInfo';
|
|
35
35
|
export type { FcmRemoteMessage, FcmConfig } from './fcm/types';
|
|
36
|
+
export type { ModuleWithStatics } from './types/Module';
|
|
37
|
+
export type { WebNotificationSettings } from './types/NotificationWeb';
|