react-native-notify-kit 10.0.0 → 10.2.0
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 +168 -100
- package/android/build.gradle +2 -2
- package/android/src/androidTest/java/app/notifee/core/RebootRecoveryTest.java +94 -2
- package/android/src/main/AndroidManifest.xml +8 -7
- package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
- package/android/src/main/java/app/notifee/core/NotificationManager.java +8 -0
- package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidModel.java +8 -3
- package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
- package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +30 -1
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
- package/android/src/test/java/app/notifee/core/model/NotificationAndroidModelSmallIconFallbackTest.java +74 -0
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +154 -0
- package/android/src/test/java/app/notifee/core/utility/ResourceUtilsFallbackIconTest.java +116 -0
- package/dist/types/Module.d.ts +7 -7
- 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/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 +42 -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 +1035 -99
- 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/server/README.md +4 -4
- package/src/types/Module.ts +7 -7
- package/src/types/Notification.ts +1 -1
- package/src/types/NotificationIOS.ts +43 -28
- package/src/types/Trigger.ts +45 -1
- package/src/validators/validateIOSCategory.ts +4 -2
- package/src/validators/validateTrigger.ts +62 -0
- package/src/version.ts +1 -1
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
#import <UIKit/UIKit.h>
|
|
19
19
|
#import <dispatch/dispatch.h>
|
|
20
|
+
#include <math.h>
|
|
20
21
|
|
|
21
22
|
#import "Intents/Intents.h"
|
|
22
23
|
#import "NotifeeCore+UNUserNotificationCenter.h"
|
|
@@ -25,8 +26,950 @@
|
|
|
25
26
|
#import "NotifeeCoreExtensionHelper.h"
|
|
26
27
|
#import "NotifeeCoreUtil.h"
|
|
27
28
|
|
|
29
|
+
static NSString *const kNotifeeRollingPublicId = @"notifee_rolling_public_id";
|
|
30
|
+
static NSString *const kNotifeeRollingOccurrenceMs = @"notifee_rolling_occurrence_ms";
|
|
31
|
+
static NSString *const kNotifeeRollingInternalId = @"notifee_rolling_internal_id";
|
|
32
|
+
static NSString *const kNotifeeRollingInternalIdPrefix = @"__notifee_rolling__";
|
|
33
|
+
static NSString *const kNotifeeCoreErrorDomain = @"app.notifee.core";
|
|
34
|
+
|
|
35
|
+
typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
|
|
36
|
+
NotifeeCoreRollingErrorCodeInvalidTrigger = 1,
|
|
37
|
+
NotifeeCoreRollingErrorCodeBudgetExceeded = 2,
|
|
38
|
+
NotifeeCoreRollingErrorCodeStorageFailed = 3,
|
|
39
|
+
};
|
|
40
|
+
|
|
28
41
|
@implementation NotifeeCore
|
|
29
42
|
|
|
43
|
+
+ (dispatch_queue_t)rollingTimestampQueue {
|
|
44
|
+
static dispatch_queue_t queue;
|
|
45
|
+
static dispatch_once_t onceToken;
|
|
46
|
+
dispatch_once(&onceToken, ^{
|
|
47
|
+
queue = dispatch_queue_create("app.notifee.core.rollingTimestamp", DISPATCH_QUEUE_SERIAL);
|
|
48
|
+
});
|
|
49
|
+
return queue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
+ (NSError *)rollingTimestampErrorWithCode:(NotifeeCoreRollingErrorCode)code
|
|
53
|
+
message:(NSString *)message {
|
|
54
|
+
return [NSError errorWithDomain:kNotifeeCoreErrorDomain
|
|
55
|
+
code:code
|
|
56
|
+
userInfo:@{NSLocalizedDescriptionKey : message}];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
+ (NSNumber *)currentTimestampMs {
|
|
60
|
+
return @((long long)llround([[NSDate date] timeIntervalSince1970] * 1000.0));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
+ (void)resolveBlock:(notifeeMethodVoidBlock)block withError:(NSError *)error {
|
|
64
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
65
|
+
block(error);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
+ (NSArray<UNNotificationRequest *> *)pendingNotificationRequests:
|
|
70
|
+
(UNUserNotificationCenter *)center {
|
|
71
|
+
__block NSArray<UNNotificationRequest *> *pendingRequests = @[];
|
|
72
|
+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
|
73
|
+
|
|
74
|
+
[center getPendingNotificationRequestsWithCompletionHandler:^(
|
|
75
|
+
NSArray<UNNotificationRequest *> *_Nonnull requests) {
|
|
76
|
+
pendingRequests = requests != nil ? requests : @[];
|
|
77
|
+
dispatch_semaphore_signal(semaphore);
|
|
78
|
+
}];
|
|
79
|
+
|
|
80
|
+
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
|
81
|
+
return pendingRequests;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
+ (NSArray<UNNotification *> *)deliveredNotifications:(UNUserNotificationCenter *)center {
|
|
85
|
+
__block NSArray<UNNotification *> *deliveredNotifications = @[];
|
|
86
|
+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
|
87
|
+
|
|
88
|
+
[center getDeliveredNotificationsWithCompletionHandler:^(
|
|
89
|
+
NSArray<UNNotification *> *_Nonnull notifications) {
|
|
90
|
+
deliveredNotifications = notifications != nil ? notifications : @[];
|
|
91
|
+
dispatch_semaphore_signal(semaphore);
|
|
92
|
+
}];
|
|
93
|
+
|
|
94
|
+
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
|
95
|
+
return deliveredNotifications;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
+ (NSString *)rollingPublicIdForNotification:(NSDictionary *)notification {
|
|
99
|
+
NSString *publicId = notification[@"id"];
|
|
100
|
+
if (![publicId isKindOfClass:NSString.class] || [publicId length] == 0) {
|
|
101
|
+
return nil;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return publicId;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
+ (BOOL)isPotentialRollingInternalNotificationId:(NSString *)notificationId {
|
|
108
|
+
return [notificationId isKindOfClass:NSString.class] &&
|
|
109
|
+
[notificationId hasPrefix:kNotifeeRollingInternalIdPrefix];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
+ (NSString *)rollingPublicIdForRequest:(UNNotificationRequest *)request {
|
|
113
|
+
NSString *identifier = request.identifier;
|
|
114
|
+
NSString *mappedPublicId =
|
|
115
|
+
[NotifeeCoreUtil rollingPublicIdFromInternalNotificationId:identifier];
|
|
116
|
+
if ([mappedPublicId isKindOfClass:NSString.class] && [mappedPublicId length] > 0) {
|
|
117
|
+
return mappedPublicId;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if ([self isPotentialRollingInternalNotificationId:identifier]) {
|
|
121
|
+
NSString *metadataPublicId = request.content.userInfo[kNotifeeRollingPublicId];
|
|
122
|
+
if ([metadataPublicId isKindOfClass:NSString.class] && [metadataPublicId length] > 0) {
|
|
123
|
+
return metadataPublicId;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
NSDictionary *notification = request.content.userInfo[kNotifeeUserInfoNotification];
|
|
127
|
+
if ([notification isKindOfClass:NSDictionary.class]) {
|
|
128
|
+
NSString *payloadPublicId = notification[@"id"];
|
|
129
|
+
if ([payloadPublicId isKindOfClass:NSString.class] && [payloadPublicId length] > 0) {
|
|
130
|
+
return payloadPublicId;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return nil;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
+ (NSString *)publicIdentifierForRequest:(UNNotificationRequest *)request {
|
|
139
|
+
NSString *rollingPublicId = [self rollingPublicIdForRequest:request];
|
|
140
|
+
if (rollingPublicId != nil) {
|
|
141
|
+
return rollingPublicId;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NSString *identifier = request.identifier;
|
|
145
|
+
if ([self isPotentialRollingInternalNotificationId:identifier]) {
|
|
146
|
+
return nil;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return identifier;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
+ (void)addString:(NSString *)string toOrderedSet:(NSMutableOrderedSet<NSString *> *)orderedSet {
|
|
153
|
+
if ([string isKindOfClass:NSString.class] && [string length] > 0) {
|
|
154
|
+
[orderedSet addObject:string];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
+ (NSMutableOrderedSet<NSString *> *)rollingIdentifiersForPublicId:(NSString *)publicId
|
|
159
|
+
pendingRequests:
|
|
160
|
+
(NSArray<UNNotificationRequest *> *)
|
|
161
|
+
pendingRequests
|
|
162
|
+
record:(NSDictionary *)record {
|
|
163
|
+
NSMutableOrderedSet<NSString *> *identifiers = [NSMutableOrderedSet orderedSet];
|
|
164
|
+
|
|
165
|
+
NSArray *scheduledIds = record[@"scheduledIds"];
|
|
166
|
+
if ([scheduledIds isKindOfClass:NSArray.class]) {
|
|
167
|
+
for (id scheduledId in scheduledIds) {
|
|
168
|
+
[self addString:scheduledId toOrderedSet:identifiers];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
for (UNNotificationRequest *request in pendingRequests) {
|
|
173
|
+
NSString *identifier = request.identifier;
|
|
174
|
+
if ([identifier isEqualToString:publicId]) {
|
|
175
|
+
[self addString:identifier toOrderedSet:identifiers];
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
NSString *mappedPublicId =
|
|
180
|
+
[NotifeeCoreUtil rollingPublicIdFromInternalNotificationId:identifier];
|
|
181
|
+
if ([mappedPublicId isEqualToString:publicId]) {
|
|
182
|
+
[self addString:identifier toOrderedSet:identifiers];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return identifiers;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
+ (NSMutableOrderedSet<NSString *> *)rollingDeliveredIdentifiersForPublicId:
|
|
190
|
+
(NSString *)publicId
|
|
191
|
+
deliveredNotifications:
|
|
192
|
+
(NSArray<UNNotification *> *)
|
|
193
|
+
deliveredNotifications
|
|
194
|
+
record:(NSDictionary *)record {
|
|
195
|
+
NSMutableOrderedSet<NSString *> *identifiers = [NSMutableOrderedSet orderedSet];
|
|
196
|
+
|
|
197
|
+
NSArray *scheduledIds = record[@"scheduledIds"];
|
|
198
|
+
if ([scheduledIds isKindOfClass:NSArray.class]) {
|
|
199
|
+
for (id scheduledId in scheduledIds) {
|
|
200
|
+
[self addString:scheduledId toOrderedSet:identifiers];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
for (UNNotification *notification in deliveredNotifications) {
|
|
205
|
+
UNNotificationRequest *request = notification.request;
|
|
206
|
+
NSString *identifier = request.identifier;
|
|
207
|
+
if ([identifier isEqualToString:publicId]) {
|
|
208
|
+
[self addString:identifier toOrderedSet:identifiers];
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
NSString *mappedPublicId = [self rollingPublicIdForRequest:request];
|
|
213
|
+
if ([mappedPublicId isEqualToString:publicId]) {
|
|
214
|
+
[self addString:identifier toOrderedSet:identifiers];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return identifiers;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
+ (NSUInteger)pendingRequestCountForIdentifiers:(NSOrderedSet<NSString *> *)identifiers
|
|
222
|
+
pendingRequests:
|
|
223
|
+
(NSArray<UNNotificationRequest *> *)pendingRequests {
|
|
224
|
+
NSUInteger count = 0;
|
|
225
|
+
for (UNNotificationRequest *request in pendingRequests) {
|
|
226
|
+
if ([identifiers containsObject:request.identifier]) {
|
|
227
|
+
count += 1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return count;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
+ (UNCalendarNotificationTrigger *)rollingOneShotTriggerForOccurrenceMs:
|
|
234
|
+
(NSNumber *)occurrenceMs {
|
|
235
|
+
NSDate *date = [NSDate dateWithTimeIntervalSince1970:([occurrenceMs doubleValue] / 1000.0)];
|
|
236
|
+
NSDateComponents *components =
|
|
237
|
+
[[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth |
|
|
238
|
+
NSCalendarUnitDay | NSCalendarUnitHour |
|
|
239
|
+
NSCalendarUnitMinute | NSCalendarUnitSecond
|
|
240
|
+
fromDate:date];
|
|
241
|
+
|
|
242
|
+
return [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
+ (UNMutableNotificationContent *)rollingContentFromContent:(UNMutableNotificationContent *)content
|
|
246
|
+
publicId:(NSString *)publicId
|
|
247
|
+
occurrenceMs:(NSNumber *)occurrenceMs
|
|
248
|
+
internalId:(NSString *)internalId {
|
|
249
|
+
UNMutableNotificationContent *rollingContent = [content mutableCopy];
|
|
250
|
+
NSMutableDictionary *userInfo = [rollingContent.userInfo mutableCopy];
|
|
251
|
+
userInfo[kNotifeeRollingPublicId] = publicId;
|
|
252
|
+
userInfo[kNotifeeRollingOccurrenceMs] = occurrenceMs;
|
|
253
|
+
userInfo[kNotifeeRollingInternalId] = internalId;
|
|
254
|
+
rollingContent.userInfo = userInfo;
|
|
255
|
+
|
|
256
|
+
return rollingContent;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
+ (UNMutableNotificationContent *)triggerNotificationContentForNotification:
|
|
260
|
+
(NSDictionary *)notification
|
|
261
|
+
trigger:(NSDictionary *)trigger {
|
|
262
|
+
UNMutableNotificationContent *content = [self buildNotificationContent:notification
|
|
263
|
+
withTrigger:trigger];
|
|
264
|
+
|
|
265
|
+
if (@available(iOS 15.0, *)) {
|
|
266
|
+
if (notification[@"ios"][@"communicationInfo"] != nil) {
|
|
267
|
+
INSendMessageIntent *intent = [NotifeeCoreUtil
|
|
268
|
+
generateSenderIntentForCommunicationNotification:notification[@"ios"]
|
|
269
|
+
[@"communicationInfo"]];
|
|
270
|
+
|
|
271
|
+
INInteraction *interaction = [[INInteraction alloc] initWithIntent:intent response:nil];
|
|
272
|
+
interaction.direction = INInteractionDirectionIncoming;
|
|
273
|
+
[interaction donateInteractionWithCompletion:^(NSError *donateError) {
|
|
274
|
+
if (donateError)
|
|
275
|
+
NSLog(@"NotifeeCore: Could not donate interaction for communication notification: %@",
|
|
276
|
+
donateError);
|
|
277
|
+
}];
|
|
278
|
+
|
|
279
|
+
NSError *contentUpdateError = nil;
|
|
280
|
+
UNNotificationContent *updatedContent =
|
|
281
|
+
[content contentByUpdatingWithProvider:intent error:&contentUpdateError];
|
|
282
|
+
if (contentUpdateError) {
|
|
283
|
+
NSLog(@"NotifeeCore: Could not update notification content with communication intent: %@",
|
|
284
|
+
contentUpdateError);
|
|
285
|
+
} else if (updatedContent != nil) {
|
|
286
|
+
content = [updatedContent mutableCopy];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return content;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
+ (UNNotificationRequest *)rollingNotificationRequestForPublicId:(NSString *)publicId
|
|
295
|
+
occurrenceMs:(NSNumber *)occurrenceMs
|
|
296
|
+
content:(UNMutableNotificationContent *)content
|
|
297
|
+
error:(NSError **)error {
|
|
298
|
+
NSString *internalId = [NotifeeCoreUtil rollingInternalNotificationIdForPublicId:publicId
|
|
299
|
+
occurrenceMs:occurrenceMs];
|
|
300
|
+
if (internalId == nil) {
|
|
301
|
+
if (error != nil) {
|
|
302
|
+
*error = [self
|
|
303
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
304
|
+
message:@"NotifeeCore: Failed to create rolling timestamp "
|
|
305
|
+
@"notification identifier."];
|
|
306
|
+
}
|
|
307
|
+
return nil;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
UNMutableNotificationContent *rollingContent = [self rollingContentFromContent:content
|
|
311
|
+
publicId:publicId
|
|
312
|
+
occurrenceMs:occurrenceMs
|
|
313
|
+
internalId:internalId];
|
|
314
|
+
return [UNNotificationRequest
|
|
315
|
+
requestWithIdentifier:internalId
|
|
316
|
+
content:rollingContent
|
|
317
|
+
trigger:[self rollingOneShotTriggerForOccurrenceMs:occurrenceMs]];
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
+ (void)removeRollingPendingRequestsForIds:(NSArray<NSString *> *)identifiers
|
|
321
|
+
center:(UNUserNotificationCenter *)center {
|
|
322
|
+
if ([identifiers count] > 0) {
|
|
323
|
+
[center removePendingNotificationRequestsWithIdentifiers:identifiers];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
+ (NSMutableSet<NSString *> *)pendingIdentifierSetFromRequests:
|
|
328
|
+
(NSArray<UNNotificationRequest *> *)pendingRequests {
|
|
329
|
+
NSMutableSet<NSString *> *identifiers = [NSMutableSet set];
|
|
330
|
+
for (UNNotificationRequest *request in pendingRequests) {
|
|
331
|
+
NSString *identifier = request.identifier;
|
|
332
|
+
if ([identifier isKindOfClass:NSString.class] && [identifier length] > 0) {
|
|
333
|
+
[identifiers addObject:identifier];
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return identifiers;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
+ (NSComparisonResult)compareRollingRebalanceState:(NSDictionary *)firstState
|
|
340
|
+
otherState:(NSDictionary *)secondState {
|
|
341
|
+
return [firstState[@"publicId"] compare:secondState[@"publicId"]];
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
+ (NSError *)scheduleRollingNotificationRequests:(NSArray<UNNotificationRequest *> *)requests
|
|
345
|
+
center:(UNUserNotificationCenter *)center
|
|
346
|
+
successfulIdentifiers:
|
|
347
|
+
(NSMutableSet<NSString *> *)successfulIdentifiers {
|
|
348
|
+
if ([requests count] == 0) {
|
|
349
|
+
return nil;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
dispatch_group_t group = dispatch_group_create();
|
|
353
|
+
NSObject *scheduleLock = [[NSObject alloc] init];
|
|
354
|
+
__block NSError *scheduleError = nil;
|
|
355
|
+
|
|
356
|
+
for (__unused UNNotificationRequest *request in requests) {
|
|
357
|
+
dispatch_group_enter(group);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
361
|
+
for (UNNotificationRequest *request in requests) {
|
|
362
|
+
[center addNotificationRequest:request
|
|
363
|
+
withCompletionHandler:^(NSError *_Nullable error) {
|
|
364
|
+
@synchronized(scheduleLock) {
|
|
365
|
+
if (error != nil && scheduleError == nil) {
|
|
366
|
+
scheduleError = error;
|
|
367
|
+
} else if (error == nil && successfulIdentifiers != nil) {
|
|
368
|
+
[successfulIdentifiers addObject:request.identifier];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
dispatch_group_leave(group);
|
|
372
|
+
}];
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
|
377
|
+
return scheduleError;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
+ (BOOL)persistedRollingRecords:(NSDictionary *)persistedRecords
|
|
381
|
+
matchUpdatedRecords:(NSDictionary *)updatedRecords {
|
|
382
|
+
if ([persistedRecords count] != [updatedRecords count]) {
|
|
383
|
+
return NO;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
for (id publicId in updatedRecords) {
|
|
387
|
+
if (persistedRecords[publicId] == nil) {
|
|
388
|
+
return NO;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return YES;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
+ (NSArray<NSMutableDictionary *> *)rollingRebalanceStatesFromRecords:(NSDictionary *)records
|
|
396
|
+
nowMs:(NSNumber *)nowMs
|
|
397
|
+
requiredPublicId:
|
|
398
|
+
(NSString *)requiredPublicId
|
|
399
|
+
error:(NSError **)error {
|
|
400
|
+
NSMutableArray<NSMutableDictionary *> *states = [NSMutableArray array];
|
|
401
|
+
BOOL foundRequiredPublicId = requiredPublicId == nil;
|
|
402
|
+
|
|
403
|
+
for (id key in records) {
|
|
404
|
+
if (![key isKindOfClass:NSString.class] || [key length] == 0) {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
NSString *publicId = key;
|
|
409
|
+
BOOL isRequiredPublicId = [publicId isEqualToString:requiredPublicId];
|
|
410
|
+
if (isRequiredPublicId) {
|
|
411
|
+
foundRequiredPublicId = YES;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
NSDictionary *record = records[publicId];
|
|
415
|
+
NSDictionary *notification = record[@"notification"];
|
|
416
|
+
NSDictionary *trigger = record[@"trigger"];
|
|
417
|
+
if (![notification isKindOfClass:NSDictionary.class] ||
|
|
418
|
+
![trigger isKindOfClass:NSDictionary.class] ||
|
|
419
|
+
![NotifeeCoreUtil isRollingTimestampTrigger:trigger]) {
|
|
420
|
+
if (isRequiredPublicId && error != nil) {
|
|
421
|
+
*error = [self
|
|
422
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
423
|
+
message:@"NotifeeCore: Rolling timestamp trigger requires a "
|
|
424
|
+
@"valid notification and trigger record."];
|
|
425
|
+
return nil;
|
|
426
|
+
}
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
NSArray<NSNumber *> *firstOccurrence =
|
|
431
|
+
[NotifeeCoreUtil rollingTimestampOccurrencesFromTrigger:trigger nowMs:nowMs maxCount:1];
|
|
432
|
+
NSNumber *firstOccurrenceMs = [firstOccurrence firstObject];
|
|
433
|
+
NSString *firstInternalId =
|
|
434
|
+
[NotifeeCoreUtil rollingInternalNotificationIdForPublicId:publicId
|
|
435
|
+
occurrenceMs:firstOccurrenceMs];
|
|
436
|
+
if (firstOccurrenceMs == nil || firstInternalId == nil) {
|
|
437
|
+
if (isRequiredPublicId && error != nil) {
|
|
438
|
+
*error = [self
|
|
439
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
440
|
+
message:@"NotifeeCore: Rolling timestamp trigger did not "
|
|
441
|
+
@"produce any future occurrences."];
|
|
442
|
+
return nil;
|
|
443
|
+
}
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
NSNumber *createdAt = record[@"createdAtMs"];
|
|
448
|
+
if (![createdAt isKindOfClass:NSNumber.class]) {
|
|
449
|
+
createdAt = nowMs;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
NSMutableDictionary *state = [NSMutableDictionary dictionary];
|
|
453
|
+
state[@"publicId"] = publicId;
|
|
454
|
+
state[@"notification"] = notification;
|
|
455
|
+
state[@"trigger"] = trigger;
|
|
456
|
+
state[@"createdAtMs"] = createdAt;
|
|
457
|
+
state[@"quota"] = @0;
|
|
458
|
+
[states addObject:state];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (!foundRequiredPublicId) {
|
|
462
|
+
if (error != nil) {
|
|
463
|
+
*error = [self rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
464
|
+
message:@"NotifeeCore: Rolling timestamp trigger "
|
|
465
|
+
@"record was not found for rebalance."];
|
|
466
|
+
}
|
|
467
|
+
return nil;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
[states sortUsingComparator:^NSComparisonResult(NSDictionary *firstState,
|
|
471
|
+
NSDictionary *secondState) {
|
|
472
|
+
return [self compareRollingRebalanceState:firstState otherState:secondState];
|
|
473
|
+
}];
|
|
474
|
+
|
|
475
|
+
return states;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
+ (BOOL)prepareRollingRebalanceDesiredSchedulesForStates:
|
|
479
|
+
(NSArray<NSMutableDictionary *> *)states
|
|
480
|
+
nowMs:(NSNumber *)nowMs
|
|
481
|
+
error:(NSError **)error {
|
|
482
|
+
for (NSMutableDictionary *state in states) {
|
|
483
|
+
NSInteger quota = [state[@"quota"] integerValue];
|
|
484
|
+
if (quota <= 0) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
NSString *publicId = state[@"publicId"];
|
|
489
|
+
NSDictionary *notification = state[@"notification"];
|
|
490
|
+
NSDictionary *trigger = state[@"trigger"];
|
|
491
|
+
NSArray<NSNumber *> *occurrences =
|
|
492
|
+
[NotifeeCoreUtil rollingTimestampOccurrencesFromTrigger:trigger
|
|
493
|
+
nowMs:nowMs
|
|
494
|
+
maxCount:quota];
|
|
495
|
+
if ([occurrences count] == 0) {
|
|
496
|
+
if (error != nil) {
|
|
497
|
+
*error = [self
|
|
498
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
499
|
+
message:@"NotifeeCore: Rolling timestamp trigger did not "
|
|
500
|
+
@"produce any future occurrences."];
|
|
501
|
+
}
|
|
502
|
+
return NO;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
UNMutableNotificationContent *content =
|
|
506
|
+
[self triggerNotificationContentForNotification:notification trigger:trigger];
|
|
507
|
+
NSMutableOrderedSet<NSString *> *desiredIds = [NSMutableOrderedSet orderedSet];
|
|
508
|
+
NSMutableDictionary<NSString *, UNNotificationRequest *> *desiredRequests =
|
|
509
|
+
[NSMutableDictionary dictionary];
|
|
510
|
+
NSNumber *lastScheduledOccurrence = nil;
|
|
511
|
+
|
|
512
|
+
for (NSNumber *occurrenceMs in occurrences) {
|
|
513
|
+
if ([desiredIds count] >= (NSUInteger)quota) {
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
NSError *requestError = nil;
|
|
518
|
+
UNNotificationRequest *request =
|
|
519
|
+
[self rollingNotificationRequestForPublicId:publicId
|
|
520
|
+
occurrenceMs:occurrenceMs
|
|
521
|
+
content:content
|
|
522
|
+
error:&requestError];
|
|
523
|
+
if (request == nil) {
|
|
524
|
+
if (error != nil) {
|
|
525
|
+
*error = requestError;
|
|
526
|
+
}
|
|
527
|
+
return NO;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if ([desiredIds containsObject:request.identifier]) {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
[desiredIds addObject:request.identifier];
|
|
535
|
+
desiredRequests[request.identifier] = request;
|
|
536
|
+
lastScheduledOccurrence = occurrenceMs;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if ([desiredIds count] == 0 || lastScheduledOccurrence == nil) {
|
|
540
|
+
if (error != nil) {
|
|
541
|
+
*error = [self
|
|
542
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
543
|
+
message:@"NotifeeCore: Rolling timestamp trigger did not "
|
|
544
|
+
@"produce any future occurrences."];
|
|
545
|
+
}
|
|
546
|
+
return NO;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
NSMutableDictionary *updatedRecord = [NSMutableDictionary dictionary];
|
|
550
|
+
updatedRecord[@"publicId"] = publicId;
|
|
551
|
+
updatedRecord[@"notification"] = notification;
|
|
552
|
+
updatedRecord[@"trigger"] = trigger;
|
|
553
|
+
updatedRecord[@"scheduledIds"] = [desiredIds array];
|
|
554
|
+
updatedRecord[@"lastScheduledOccurrenceMs"] = lastScheduledOccurrence;
|
|
555
|
+
updatedRecord[@"createdAtMs"] = state[@"createdAtMs"];
|
|
556
|
+
|
|
557
|
+
state[@"desiredIds"] = desiredIds;
|
|
558
|
+
state[@"desiredRequests"] = desiredRequests;
|
|
559
|
+
state[@"updatedRecord"] = updatedRecord;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return YES;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
+ (void)rollbackRollingRebalanceRemovedRequests:
|
|
566
|
+
(NSArray<UNNotificationRequest *> *)removedRequests
|
|
567
|
+
successfulNewIdentifiers:(NSSet<NSString *> *)successfulNewIdentifiers
|
|
568
|
+
center:(UNUserNotificationCenter *)center {
|
|
569
|
+
if ([successfulNewIdentifiers count] > 0) {
|
|
570
|
+
[self removeRollingPendingRequestsForIds:[successfulNewIdentifiers allObjects] center:center];
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if ([removedRequests count] > 0) {
|
|
574
|
+
[self scheduleRollingNotificationRequests:removedRequests
|
|
575
|
+
center:center
|
|
576
|
+
successfulIdentifiers:nil];
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
+ (BOOL)rebalanceRollingTimestampTriggerRecords:(NSDictionary *)records
|
|
581
|
+
center:(UNUserNotificationCenter *)center
|
|
582
|
+
pendingRequests:
|
|
583
|
+
(NSArray<UNNotificationRequest *> *)pendingRequests
|
|
584
|
+
nowMs:(NSNumber *)nowMs
|
|
585
|
+
refreshPublicId:(NSString *)refreshPublicId
|
|
586
|
+
requiredPublicId:(NSString *)requiredPublicId
|
|
587
|
+
error:(NSError **)error {
|
|
588
|
+
NSError *stateError = nil;
|
|
589
|
+
NSArray<NSMutableDictionary *> *states =
|
|
590
|
+
[self rollingRebalanceStatesFromRecords:records
|
|
591
|
+
nowMs:nowMs
|
|
592
|
+
requiredPublicId:requiredPublicId
|
|
593
|
+
error:&stateError];
|
|
594
|
+
if (states == nil) {
|
|
595
|
+
if (error != nil) {
|
|
596
|
+
*error = stateError;
|
|
597
|
+
}
|
|
598
|
+
return NO;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
NSMutableSet<NSString *> *pendingIdentifierSet =
|
|
602
|
+
[self pendingIdentifierSetFromRequests:pendingRequests];
|
|
603
|
+
NSMutableDictionary<NSString *, UNNotificationRequest *> *pendingRequestByIdentifier =
|
|
604
|
+
[NSMutableDictionary dictionary];
|
|
605
|
+
NSMutableOrderedSet<NSString *> *rollingPendingIdentifiers = [NSMutableOrderedSet orderedSet];
|
|
606
|
+
NSMutableOrderedSet<NSString *> *replacementPendingIdentifiers = [NSMutableOrderedSet orderedSet];
|
|
607
|
+
NSInteger nonRollingPendingCount = 0;
|
|
608
|
+
|
|
609
|
+
for (UNNotificationRequest *request in pendingRequests) {
|
|
610
|
+
NSString *identifier = request.identifier;
|
|
611
|
+
if (![identifier isKindOfClass:NSString.class] || [identifier length] == 0) {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
pendingRequestByIdentifier[identifier] = request;
|
|
616
|
+
if ([self isPotentialRollingInternalNotificationId:identifier]) {
|
|
617
|
+
[rollingPendingIdentifiers addObject:identifier];
|
|
618
|
+
} else if ([identifier isEqualToString:refreshPublicId]) {
|
|
619
|
+
[replacementPendingIdentifiers addObject:identifier];
|
|
620
|
+
} else {
|
|
621
|
+
nonRollingPendingCount += 1;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
NSInteger rollingBudget = [NotifeeCoreUtil rollingPendingBudget] - nonRollingPendingCount;
|
|
626
|
+
if (rollingBudget < 0) {
|
|
627
|
+
rollingBudget = 0;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if ((NSInteger)[states count] > rollingBudget) {
|
|
631
|
+
if (error != nil) {
|
|
632
|
+
*error = [self
|
|
633
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeBudgetExceeded
|
|
634
|
+
message:@"NotifeeCore: iOS rolling timestamp trigger budget "
|
|
635
|
+
@"cannot allocate one occurrence per active trigger."];
|
|
636
|
+
}
|
|
637
|
+
return NO;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
NSInteger targetPerTrigger = [NotifeeCoreUtil rollingTargetPerTrigger];
|
|
641
|
+
NSInteger remainingBudget = rollingBudget;
|
|
642
|
+
for (NSMutableDictionary *state in states) {
|
|
643
|
+
state[@"quota"] = @1;
|
|
644
|
+
remainingBudget -= 1;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
BOOL allocatedAdditionalSlot = YES;
|
|
648
|
+
while (remainingBudget > 0 && allocatedAdditionalSlot) {
|
|
649
|
+
allocatedAdditionalSlot = NO;
|
|
650
|
+
for (NSMutableDictionary *state in states) {
|
|
651
|
+
if (remainingBudget <= 0) {
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
NSInteger quota = [state[@"quota"] integerValue];
|
|
656
|
+
if (quota >= targetPerTrigger) {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
state[@"quota"] = @(quota + 1);
|
|
661
|
+
remainingBudget -= 1;
|
|
662
|
+
allocatedAdditionalSlot = YES;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
NSError *planError = nil;
|
|
667
|
+
if (![self prepareRollingRebalanceDesiredSchedulesForStates:states
|
|
668
|
+
nowMs:nowMs
|
|
669
|
+
error:&planError]) {
|
|
670
|
+
if (error != nil) {
|
|
671
|
+
*error = planError;
|
|
672
|
+
}
|
|
673
|
+
return NO;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
NSMutableOrderedSet<NSString *> *desiredIdentifiers = [NSMutableOrderedSet orderedSet];
|
|
677
|
+
NSMutableDictionary *updatedRecords = [NSMutableDictionary dictionary];
|
|
678
|
+
for (NSMutableDictionary *state in states) {
|
|
679
|
+
NSOrderedSet<NSString *> *stateDesiredIds = state[@"desiredIds"];
|
|
680
|
+
[desiredIdentifiers unionOrderedSet:stateDesiredIds];
|
|
681
|
+
|
|
682
|
+
NSString *publicId = state[@"publicId"];
|
|
683
|
+
NSDictionary *updatedRecord = state[@"updatedRecord"];
|
|
684
|
+
if (publicId != nil && updatedRecord != nil) {
|
|
685
|
+
updatedRecords[publicId] = updatedRecord;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (requiredPublicId != nil && updatedRecords[requiredPublicId] == nil) {
|
|
690
|
+
if (error != nil) {
|
|
691
|
+
*error = [self
|
|
692
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
693
|
+
message:@"NotifeeCore: Rolling timestamp trigger did not produce "
|
|
694
|
+
@"any future occurrences."];
|
|
695
|
+
}
|
|
696
|
+
return NO;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
NSMutableOrderedSet<NSString *> *identifiersToRemove = [NSMutableOrderedSet orderedSet];
|
|
700
|
+
for (NSString *identifier in rollingPendingIdentifiers) {
|
|
701
|
+
if (![desiredIdentifiers containsObject:identifier]) {
|
|
702
|
+
[identifiersToRemove addObject:identifier];
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
[identifiersToRemove unionOrderedSet:replacementPendingIdentifiers];
|
|
706
|
+
|
|
707
|
+
NSMutableArray<UNNotificationRequest *> *removedRequests = [NSMutableArray array];
|
|
708
|
+
for (NSString *identifier in identifiersToRemove) {
|
|
709
|
+
UNNotificationRequest *request = pendingRequestByIdentifier[identifier];
|
|
710
|
+
if (request != nil) {
|
|
711
|
+
[removedRequests addObject:request];
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
NSMutableArray<UNNotificationRequest *> *requestsToSchedule = [NSMutableArray array];
|
|
716
|
+
NSMutableSet<NSString *> *newRequestIdentifiers = [NSMutableSet set];
|
|
717
|
+
for (NSMutableDictionary *state in states) {
|
|
718
|
+
NSString *publicId = state[@"publicId"];
|
|
719
|
+
NSOrderedSet<NSString *> *stateDesiredIds = state[@"desiredIds"];
|
|
720
|
+
NSDictionary<NSString *, UNNotificationRequest *> *desiredRequests = state[@"desiredRequests"];
|
|
721
|
+
BOOL shouldRefresh = refreshPublicId != nil && [publicId isEqualToString:refreshPublicId];
|
|
722
|
+
|
|
723
|
+
for (NSString *identifier in stateDesiredIds) {
|
|
724
|
+
UNNotificationRequest *request = desiredRequests[identifier];
|
|
725
|
+
if (request == nil) {
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
BOOL isAlreadyPending = [pendingIdentifierSet containsObject:identifier];
|
|
730
|
+
if (!isAlreadyPending || shouldRefresh) {
|
|
731
|
+
[requestsToSchedule addObject:request];
|
|
732
|
+
}
|
|
733
|
+
if (!isAlreadyPending) {
|
|
734
|
+
[newRequestIdentifiers addObject:identifier];
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
[self removeRollingPendingRequestsForIds:[identifiersToRemove array] center:center];
|
|
740
|
+
|
|
741
|
+
NSMutableSet<NSString *> *successfulScheduledIdentifiers = [NSMutableSet set];
|
|
742
|
+
NSError *scheduleError =
|
|
743
|
+
[self scheduleRollingNotificationRequests:requestsToSchedule
|
|
744
|
+
center:center
|
|
745
|
+
successfulIdentifiers:successfulScheduledIdentifiers];
|
|
746
|
+
if (scheduleError != nil) {
|
|
747
|
+
NSMutableSet<NSString *> *successfulNewIdentifiers = [NSMutableSet set];
|
|
748
|
+
for (NSString *identifier in successfulScheduledIdentifiers) {
|
|
749
|
+
if ([newRequestIdentifiers containsObject:identifier]) {
|
|
750
|
+
[successfulNewIdentifiers addObject:identifier];
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
[self rollbackRollingRebalanceRemovedRequests:removedRequests
|
|
755
|
+
successfulNewIdentifiers:successfulNewIdentifiers
|
|
756
|
+
center:center];
|
|
757
|
+
if (error != nil) {
|
|
758
|
+
*error = scheduleError;
|
|
759
|
+
}
|
|
760
|
+
return NO;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
[NotifeeCoreUtil setRollingTimestampTriggers:updatedRecords];
|
|
764
|
+
NSDictionary *persistedRecords = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
765
|
+
if (![self persistedRollingRecords:persistedRecords matchUpdatedRecords:updatedRecords]) {
|
|
766
|
+
NSMutableSet<NSString *> *successfulNewIdentifiers = [NSMutableSet set];
|
|
767
|
+
for (NSString *identifier in successfulScheduledIdentifiers) {
|
|
768
|
+
if ([newRequestIdentifiers containsObject:identifier]) {
|
|
769
|
+
[successfulNewIdentifiers addObject:identifier];
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
[self removeRollingPendingRequestsForIds:[successfulNewIdentifiers allObjects] center:center];
|
|
773
|
+
|
|
774
|
+
if (error != nil) {
|
|
775
|
+
*error = [self
|
|
776
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeStorageFailed
|
|
777
|
+
message:@"NotifeeCore: Failed to persist rolling timestamp "
|
|
778
|
+
@"trigger records after rebalance."];
|
|
779
|
+
}
|
|
780
|
+
return NO;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return YES;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
+ (void)topUpRollingTimestampTriggersWithCompletion:(void (^)(NSError *error))completion {
|
|
787
|
+
dispatch_async([self rollingTimestampQueue], ^{
|
|
788
|
+
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
789
|
+
NSNumber *nowMs = [self currentTimestampMs];
|
|
790
|
+
NSArray<UNNotificationRequest *> *pendingRequests = [self pendingNotificationRequests:center];
|
|
791
|
+
NSMutableDictionary *records = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
792
|
+
NSError *topUpError = nil;
|
|
793
|
+
|
|
794
|
+
[self rebalanceRollingTimestampTriggerRecords:records
|
|
795
|
+
center:center
|
|
796
|
+
pendingRequests:pendingRequests
|
|
797
|
+
nowMs:nowMs
|
|
798
|
+
refreshPublicId:nil
|
|
799
|
+
requiredPublicId:nil
|
|
800
|
+
error:&topUpError];
|
|
801
|
+
|
|
802
|
+
if (completion != nil) {
|
|
803
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
804
|
+
completion(topUpError);
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
+ (void)createRollingTriggerNotification:(NSDictionary *)notification
|
|
811
|
+
withTrigger:(NSDictionary *)trigger
|
|
812
|
+
withNotificationDetail:(NSDictionary *)notificationDetail
|
|
813
|
+
center:(UNUserNotificationCenter *)center
|
|
814
|
+
block:(notifeeMethodVoidBlock)block {
|
|
815
|
+
dispatch_async([self rollingTimestampQueue], ^{
|
|
816
|
+
NSString *publicId = [self rollingPublicIdForNotification:notification];
|
|
817
|
+
if (publicId == nil) {
|
|
818
|
+
NSError *error = [self
|
|
819
|
+
rollingTimestampErrorWithCode:NotifeeCoreRollingErrorCodeInvalidTrigger
|
|
820
|
+
message:@"NotifeeCore: Rolling timestamp trigger requires a "
|
|
821
|
+
@"notification id."];
|
|
822
|
+
[self resolveBlock:block withError:error];
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
NSArray<UNNotificationRequest *> *pendingRequests = [self pendingNotificationRequests:center];
|
|
827
|
+
NSMutableDictionary *records = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
828
|
+
NSNumber *nowMs = [self currentTimestampMs];
|
|
829
|
+
NSDictionary *record = @{
|
|
830
|
+
@"publicId" : publicId,
|
|
831
|
+
@"notification" : notification,
|
|
832
|
+
@"trigger" : trigger,
|
|
833
|
+
@"scheduledIds" : @[],
|
|
834
|
+
@"createdAtMs" : nowMs
|
|
835
|
+
};
|
|
836
|
+
records[publicId] = record;
|
|
837
|
+
|
|
838
|
+
NSError *rebalanceError = nil;
|
|
839
|
+
if (![self rebalanceRollingTimestampTriggerRecords:records
|
|
840
|
+
center:center
|
|
841
|
+
pendingRequests:pendingRequests
|
|
842
|
+
nowMs:nowMs
|
|
843
|
+
refreshPublicId:publicId
|
|
844
|
+
requiredPublicId:publicId
|
|
845
|
+
error:&rebalanceError]) {
|
|
846
|
+
[self resolveBlock:block withError:rebalanceError];
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
851
|
+
[[NotifeeCoreDelegateHolder instance] didReceiveNotifeeCoreEvent:@{
|
|
852
|
+
@"type" : @(NotifeeCoreEventTypeTriggerNotificationCreated),
|
|
853
|
+
@"detail" : @{
|
|
854
|
+
@"notification" : notificationDetail,
|
|
855
|
+
}
|
|
856
|
+
}];
|
|
857
|
+
block(nil);
|
|
858
|
+
});
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
+ (void)cancelRollingNotification:(NSString *)notificationId
|
|
863
|
+
withNotificationType:(NSInteger)notificationType
|
|
864
|
+
block:(notifeeMethodVoidBlock)block {
|
|
865
|
+
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
866
|
+
BOOL cancelDisplayed = notificationType == NotifeeCoreNotificationTypeDisplayed ||
|
|
867
|
+
notificationType == NotifeeCoreNotificationTypeAll;
|
|
868
|
+
BOOL cancelTrigger = notificationType == NotifeeCoreNotificationTypeTrigger ||
|
|
869
|
+
notificationType == NotifeeCoreNotificationTypeAll;
|
|
870
|
+
|
|
871
|
+
if (!cancelDisplayed && !cancelTrigger) {
|
|
872
|
+
block(nil);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
dispatch_async([self rollingTimestampQueue], ^{
|
|
877
|
+
NSDictionary *records = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
878
|
+
NSDictionary *record = records[notificationId];
|
|
879
|
+
|
|
880
|
+
if (cancelDisplayed) {
|
|
881
|
+
NSArray<UNNotification *> *deliveredNotifications = [self deliveredNotifications:center];
|
|
882
|
+
NSMutableOrderedSet<NSString *> *deliveredIdentifiersToRemove =
|
|
883
|
+
[self rollingDeliveredIdentifiersForPublicId:notificationId
|
|
884
|
+
deliveredNotifications:deliveredNotifications
|
|
885
|
+
record:record];
|
|
886
|
+
[self addString:notificationId toOrderedSet:deliveredIdentifiersToRemove];
|
|
887
|
+
if ([deliveredIdentifiersToRemove count] > 0) {
|
|
888
|
+
[center removeDeliveredNotificationsWithIdentifiers:[deliveredIdentifiersToRemove array]];
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
if (cancelTrigger) {
|
|
893
|
+
NSArray<UNNotificationRequest *> *pendingRequests = [self pendingNotificationRequests:center];
|
|
894
|
+
NSMutableOrderedSet<NSString *> *pendingIdentifiersToRemove =
|
|
895
|
+
[self rollingIdentifiersForPublicId:notificationId
|
|
896
|
+
pendingRequests:pendingRequests
|
|
897
|
+
record:record];
|
|
898
|
+
[self addString:notificationId toOrderedSet:pendingIdentifiersToRemove];
|
|
899
|
+
|
|
900
|
+
[self removeRollingPendingRequestsForIds:[pendingIdentifiersToRemove array] center:center];
|
|
901
|
+
if (record != nil) {
|
|
902
|
+
[NotifeeCoreUtil removeRollingTimestampTriggerRecordForPublicId:notificationId];
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
[self resolveBlock:block withError:nil];
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
+ (void)cancelRollingNotificationsWithIds:(NSArray<NSString *> *)ids
|
|
911
|
+
withNotificationType:(NSInteger)notificationType
|
|
912
|
+
block:(notifeeMethodVoidBlock)block {
|
|
913
|
+
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
914
|
+
BOOL cancelDisplayed = notificationType == NotifeeCoreNotificationTypeDisplayed ||
|
|
915
|
+
notificationType == NotifeeCoreNotificationTypeAll;
|
|
916
|
+
BOOL cancelTrigger = notificationType == NotifeeCoreNotificationTypeTrigger ||
|
|
917
|
+
notificationType == NotifeeCoreNotificationTypeAll;
|
|
918
|
+
|
|
919
|
+
NSMutableOrderedSet<NSString *> *publicIds = [NSMutableOrderedSet orderedSet];
|
|
920
|
+
for (id notificationId in ids) {
|
|
921
|
+
[self addString:notificationId toOrderedSet:publicIds];
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
if (!cancelDisplayed && !cancelTrigger) {
|
|
925
|
+
block(nil);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
dispatch_async([self rollingTimestampQueue], ^{
|
|
930
|
+
NSDictionary *records = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
931
|
+
NSArray<UNNotification *> *deliveredNotifications =
|
|
932
|
+
cancelDisplayed ? [self deliveredNotifications:center] : @[];
|
|
933
|
+
NSArray<UNNotificationRequest *> *pendingRequests =
|
|
934
|
+
cancelTrigger ? [self pendingNotificationRequests:center] : @[];
|
|
935
|
+
NSMutableOrderedSet<NSString *> *deliveredIdentifiersToRemove =
|
|
936
|
+
[NSMutableOrderedSet orderedSet];
|
|
937
|
+
NSMutableOrderedSet<NSString *> *pendingIdentifiersToRemove =
|
|
938
|
+
[NSMutableOrderedSet orderedSet];
|
|
939
|
+
|
|
940
|
+
for (NSString *publicId in publicIds) {
|
|
941
|
+
NSDictionary *record = records[publicId];
|
|
942
|
+
|
|
943
|
+
if (cancelDisplayed) {
|
|
944
|
+
NSMutableOrderedSet<NSString *> *rollingDeliveredIdentifiers =
|
|
945
|
+
[self rollingDeliveredIdentifiersForPublicId:publicId
|
|
946
|
+
deliveredNotifications:deliveredNotifications
|
|
947
|
+
record:record];
|
|
948
|
+
[deliveredIdentifiersToRemove unionOrderedSet:rollingDeliveredIdentifiers];
|
|
949
|
+
[self addString:publicId toOrderedSet:deliveredIdentifiersToRemove];
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
if (cancelTrigger) {
|
|
953
|
+
NSMutableOrderedSet<NSString *> *rollingPendingIdentifiers =
|
|
954
|
+
[self rollingIdentifiersForPublicId:publicId
|
|
955
|
+
pendingRequests:pendingRequests
|
|
956
|
+
record:record];
|
|
957
|
+
[pendingIdentifiersToRemove unionOrderedSet:rollingPendingIdentifiers];
|
|
958
|
+
[self addString:publicId toOrderedSet:pendingIdentifiersToRemove];
|
|
959
|
+
if (record != nil) {
|
|
960
|
+
[NotifeeCoreUtil removeRollingTimestampTriggerRecordForPublicId:publicId];
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
if ([deliveredIdentifiersToRemove count] > 0) {
|
|
966
|
+
[center removeDeliveredNotificationsWithIdentifiers:[deliveredIdentifiersToRemove array]];
|
|
967
|
+
}
|
|
968
|
+
[self removeRollingPendingRequestsForIds:[pendingIdentifiersToRemove array] center:center];
|
|
969
|
+
[self resolveBlock:block withError:nil];
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
|
|
30
973
|
#pragma mark - Library Methods
|
|
31
974
|
|
|
32
975
|
+ (void)setCoreDelegate:(id<NotifeeCoreDelegate>)coreDelegate {
|
|
@@ -42,17 +985,9 @@
|
|
|
42
985
|
+ (void)cancelNotification:(NSString *)notificationId
|
|
43
986
|
withNotificationType:(NSInteger)notificationType
|
|
44
987
|
withBlock:(notifeeMethodVoidBlock)block {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
notificationType == NotifeeCoreNotificationTypeAll)
|
|
49
|
-
[center removeDeliveredNotificationsWithIdentifiers:@[ notificationId ]];
|
|
50
|
-
|
|
51
|
-
// cancel trigger notification
|
|
52
|
-
if (notificationType == NotifeeCoreNotificationTypeTrigger ||
|
|
53
|
-
notificationType == NotifeeCoreNotificationTypeAll)
|
|
54
|
-
[center removePendingNotificationRequestsWithIdentifiers:@[ notificationId ]];
|
|
55
|
-
block(nil);
|
|
988
|
+
[self cancelRollingNotification:notificationId
|
|
989
|
+
withNotificationType:notificationType
|
|
990
|
+
block:block];
|
|
56
991
|
}
|
|
57
992
|
|
|
58
993
|
/**
|
|
@@ -69,11 +1004,17 @@
|
|
|
69
1004
|
notificationType == NotifeeCoreNotificationTypeAll)
|
|
70
1005
|
[center removeAllDeliveredNotifications];
|
|
71
1006
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
1007
|
+
if (notificationType != NotifeeCoreNotificationTypeTrigger &&
|
|
1008
|
+
notificationType != NotifeeCoreNotificationTypeAll) {
|
|
1009
|
+
block(nil);
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
dispatch_async([self rollingTimestampQueue], ^{
|
|
75
1014
|
[center removeAllPendingNotificationRequests];
|
|
76
|
-
|
|
1015
|
+
[NotifeeCoreUtil clearRollingTimestampTriggerRecords];
|
|
1016
|
+
[self resolveBlock:block withError:nil];
|
|
1017
|
+
});
|
|
77
1018
|
}
|
|
78
1019
|
|
|
79
1020
|
/**
|
|
@@ -86,18 +1027,7 @@
|
|
|
86
1027
|
+ (void)cancelAllNotificationsWithIds:(NSInteger)notificationType
|
|
87
1028
|
withIds:(NSArray<NSString *> *)ids
|
|
88
1029
|
withBlock:(notifeeMethodVoidBlock)block {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
// cancel displayed notifications
|
|
92
|
-
if (notificationType == NotifeeCoreNotificationTypeDisplayed ||
|
|
93
|
-
notificationType == NotifeeCoreNotificationTypeAll)
|
|
94
|
-
[center removeDeliveredNotificationsWithIdentifiers:ids];
|
|
95
|
-
|
|
96
|
-
// cancel trigger notifications
|
|
97
|
-
if (notificationType == NotifeeCoreNotificationTypeTrigger ||
|
|
98
|
-
notificationType == NotifeeCoreNotificationTypeAll)
|
|
99
|
-
[center removePendingNotificationRequestsWithIdentifiers:ids];
|
|
100
|
-
block(nil);
|
|
1030
|
+
[self cancelRollingNotificationsWithIds:ids withNotificationType:notificationType block:block];
|
|
101
1031
|
}
|
|
102
1032
|
|
|
103
1033
|
+ (void)getDisplayedNotifications:(notifeeMethodNSArrayBlock)block {
|
|
@@ -106,20 +1036,33 @@
|
|
|
106
1036
|
[center getDeliveredNotificationsWithCompletionHandler:^(
|
|
107
1037
|
NSArray<UNNotification *> *_Nonnull deliveredNotifications) {
|
|
108
1038
|
for (UNNotification *deliveredNotification in deliveredNotifications) {
|
|
1039
|
+
UNNotificationRequest *request = deliveredNotification.request;
|
|
1040
|
+
NSString *notificationId = [self publicIdentifierForRequest:request];
|
|
1041
|
+
if (notificationId == nil) {
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
109
1045
|
NSMutableDictionary *triggerNotification = [NSMutableDictionary dictionary];
|
|
110
|
-
triggerNotification[@"id"] =
|
|
1046
|
+
triggerNotification[@"id"] = notificationId;
|
|
111
1047
|
|
|
112
1048
|
triggerNotification[@"date"] =
|
|
113
1049
|
[NotifeeCoreUtil convertToTimestamp:deliveredNotification.date];
|
|
114
1050
|
triggerNotification[@"notification"] =
|
|
115
|
-
|
|
1051
|
+
request.content.userInfo[kNotifeeUserInfoNotification];
|
|
116
1052
|
triggerNotification[@"trigger"] =
|
|
117
|
-
|
|
1053
|
+
request.content.userInfo[kNotifeeUserInfoTrigger];
|
|
118
1054
|
|
|
119
1055
|
if (triggerNotification[@"notification"] == nil) {
|
|
120
1056
|
// parse remote notification
|
|
121
|
-
triggerNotification[@"notification"] =
|
|
122
|
-
|
|
1057
|
+
triggerNotification[@"notification"] = [NotifeeCoreUtil parseUNNotificationRequest:request];
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
NSString *rollingPublicId = [self rollingPublicIdForRequest:request];
|
|
1061
|
+
NSDictionary *notification = triggerNotification[@"notification"];
|
|
1062
|
+
if (rollingPublicId != nil && [notification isKindOfClass:NSDictionary.class]) {
|
|
1063
|
+
NSMutableDictionary *publicNotification = [notification mutableCopy];
|
|
1064
|
+
publicNotification[@"id"] = rollingPublicId;
|
|
1065
|
+
triggerNotification[@"notification"] = publicNotification;
|
|
123
1066
|
}
|
|
124
1067
|
|
|
125
1068
|
[triggerNotifications addObject:triggerNotification];
|
|
@@ -133,9 +1076,41 @@
|
|
|
133
1076
|
|
|
134
1077
|
[center getPendingNotificationRequestsWithCompletionHandler:^(
|
|
135
1078
|
NSArray<UNNotificationRequest *> *_Nonnull requests) {
|
|
1079
|
+
NSDictionary *rollingRecords = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
1080
|
+
NSMutableSet<NSString *> *rollingPublicIds = [NSMutableSet set];
|
|
136
1081
|
NSMutableArray *triggerNotifications = [[NSMutableArray alloc] init];
|
|
137
1082
|
|
|
1083
|
+
for (id publicId in rollingRecords) {
|
|
1084
|
+
if (![publicId isKindOfClass:NSString.class]) {
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
NSDictionary *record = rollingRecords[publicId];
|
|
1089
|
+
NSDictionary *notification = record[@"notification"];
|
|
1090
|
+
NSDictionary *trigger = record[@"trigger"];
|
|
1091
|
+
if (![notification isKindOfClass:NSDictionary.class] ||
|
|
1092
|
+
![trigger isKindOfClass:NSDictionary.class]) {
|
|
1093
|
+
continue;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
NSMutableDictionary *triggerNotification = [NSMutableDictionary dictionary];
|
|
1097
|
+
triggerNotification[@"notification"] = notification;
|
|
1098
|
+
triggerNotification[@"trigger"] = trigger;
|
|
1099
|
+
[triggerNotifications addObject:triggerNotification];
|
|
1100
|
+
[rollingPublicIds addObject:publicId];
|
|
1101
|
+
}
|
|
1102
|
+
|
|
138
1103
|
for (UNNotificationRequest *request in requests) {
|
|
1104
|
+
NSString *rollingPublicId =
|
|
1105
|
+
[NotifeeCoreUtil rollingPublicIdFromInternalNotificationId:request.identifier];
|
|
1106
|
+
if (rollingPublicId != nil) {
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
if ([rollingPublicIds containsObject:request.identifier]) {
|
|
1111
|
+
continue;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
139
1114
|
NSMutableDictionary *triggerNotification = [NSMutableDictionary dictionary];
|
|
140
1115
|
|
|
141
1116
|
triggerNotification[@"notification"] = request.content.userInfo[kNotifeeUserInfoNotification];
|
|
@@ -158,14 +1133,22 @@
|
|
|
158
1133
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
159
1134
|
[center getPendingNotificationRequestsWithCompletionHandler:^(
|
|
160
1135
|
NSArray<UNNotificationRequest *> *_Nonnull requests) {
|
|
161
|
-
|
|
1136
|
+
NSMutableOrderedSet<NSString *> *ids = [NSMutableOrderedSet orderedSet];
|
|
162
1137
|
|
|
163
1138
|
for (UNNotificationRequest *request in requests) {
|
|
164
1139
|
NSString *notificationId = request.identifier;
|
|
165
|
-
|
|
1140
|
+
NSString *rollingPublicId =
|
|
1141
|
+
[NotifeeCoreUtil rollingPublicIdFromInternalNotificationId:notificationId];
|
|
1142
|
+
[self addString:(rollingPublicId != nil ? rollingPublicId : notificationId)
|
|
1143
|
+
toOrderedSet:ids];
|
|
166
1144
|
}
|
|
167
1145
|
|
|
168
|
-
|
|
1146
|
+
NSDictionary *rollingRecords = [NotifeeCoreUtil getRollingTimestampTriggers];
|
|
1147
|
+
for (id publicId in rollingRecords) {
|
|
1148
|
+
[self addString:publicId toOrderedSet:ids];
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
block(nil, [ids array]);
|
|
169
1152
|
}];
|
|
170
1153
|
}
|
|
171
1154
|
|
|
@@ -253,47 +1236,29 @@
|
|
|
253
1236
|
withTrigger:(NSDictionary *)trigger
|
|
254
1237
|
withBlock:(notifeeMethodVoidBlock)block {
|
|
255
1238
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
256
|
-
UNMutableNotificationContent *content = [self
|
|
257
|
-
|
|
258
|
-
UNNotificationTrigger *unTrigger = [NotifeeCoreUtil triggerFromDictionary:trigger];
|
|
259
|
-
|
|
260
|
-
if (unTrigger == nil) {
|
|
261
|
-
// do nothing if trigger is null
|
|
262
|
-
return dispatch_async(dispatch_get_main_queue(), ^{
|
|
263
|
-
block(nil);
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
1239
|
+
UNMutableNotificationContent *content = [self triggerNotificationContentForNotification:notification
|
|
1240
|
+
trigger:trigger];
|
|
267
1241
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
268
1242
|
|
|
269
1243
|
NSMutableDictionary *notificationDetail = [notification mutableCopy];
|
|
270
1244
|
notificationDetail[@"remote"] = @NO;
|
|
271
1245
|
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
1246
|
+
if ([NotifeeCoreUtil isRollingTimestampTrigger:trigger]) {
|
|
1247
|
+
[self createRollingTriggerNotification:notification
|
|
1248
|
+
withTrigger:trigger
|
|
1249
|
+
withNotificationDetail:notificationDetail
|
|
1250
|
+
center:center
|
|
1251
|
+
block:block];
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
277
1254
|
|
|
278
|
-
|
|
279
|
-
INInteraction *interaction = [[INInteraction alloc] initWithIntent:intent response:nil];
|
|
280
|
-
interaction.direction = INInteractionDirectionIncoming;
|
|
281
|
-
[interaction donateInteractionWithCompletion:^(NSError *donateError) {
|
|
282
|
-
if (donateError)
|
|
283
|
-
NSLog(@"NotifeeCore: Could not donate interaction for communication notification: %@",
|
|
284
|
-
donateError);
|
|
285
|
-
}];
|
|
1255
|
+
UNNotificationTrigger *unTrigger = [NotifeeCoreUtil triggerFromDictionary:trigger];
|
|
286
1256
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
contentUpdateError);
|
|
293
|
-
} else if (updatedContent != nil) {
|
|
294
|
-
content = [updatedContent mutableCopy];
|
|
295
|
-
}
|
|
296
|
-
}
|
|
1257
|
+
if (unTrigger == nil) {
|
|
1258
|
+
// do nothing if trigger is null
|
|
1259
|
+
return dispatch_async(dispatch_get_main_queue(), ^{
|
|
1260
|
+
block(nil);
|
|
1261
|
+
});
|
|
297
1262
|
}
|
|
298
1263
|
|
|
299
1264
|
UNNotificationRequest *request =
|
|
@@ -447,18 +1412,6 @@
|
|
|
447
1412
|
content.threadIdentifier = iosDict[@"threadId"];
|
|
448
1413
|
}
|
|
449
1414
|
|
|
450
|
-
if (@available(iOS 12.0, *)) {
|
|
451
|
-
// summaryArgument
|
|
452
|
-
if (iosDict[@"summaryArgument"] != nil) {
|
|
453
|
-
content.summaryArgument = iosDict[@"summaryArgument"];
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// summaryArgumentCount
|
|
457
|
-
if (iosDict[@"summaryArgumentCount"] != nil) {
|
|
458
|
-
content.summaryArgumentCount = [iosDict[@"summaryArgumentCount"] unsignedIntValue];
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
1415
|
if (@available(iOS 13.0, *)) {
|
|
463
1416
|
// targetContentId
|
|
464
1417
|
if (iosDict[@"targetContentId"] != nil) {
|
|
@@ -512,12 +1465,7 @@
|
|
|
512
1465
|
}
|
|
513
1466
|
}
|
|
514
1467
|
|
|
515
|
-
|
|
516
|
-
categoryDictionary[@"allowAnnouncement"] = @(
|
|
517
|
-
((notificationCategory.options & UNNotificationCategoryOptionAllowAnnouncement) != 0));
|
|
518
|
-
} else {
|
|
519
|
-
categoryDictionary[@"allowAnnouncement"] = @(NO);
|
|
520
|
-
}
|
|
1468
|
+
categoryDictionary[@"allowAnnouncement"] = @(NO);
|
|
521
1469
|
|
|
522
1470
|
categoryDictionary[@"actions"] =
|
|
523
1471
|
[NotifeeCoreUtil notificationActionsToDictionaryArray:notificationCategory.actions];
|
|
@@ -570,12 +1518,6 @@
|
|
|
570
1518
|
}
|
|
571
1519
|
}
|
|
572
1520
|
|
|
573
|
-
if (@available(iOS 13.0, *)) {
|
|
574
|
-
if ([categoryDictionary[@"allowAnnouncement"] isEqual:@(YES)]) {
|
|
575
|
-
options |= UNNotificationCategoryOptionAllowAnnouncement;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
1521
|
if (@available(iOS 12.0, *)) {
|
|
580
1522
|
category = [UNNotificationCategory categoryWithIdentifier:id
|
|
581
1523
|
actions:actions
|
|
@@ -641,12 +1583,6 @@
|
|
|
641
1583
|
}
|
|
642
1584
|
}
|
|
643
1585
|
|
|
644
|
-
if ([permissions[@"announcement"] isEqual:@(YES)]) {
|
|
645
|
-
if (@available(iOS 13.0, *)) {
|
|
646
|
-
options |= UNAuthorizationOptionAnnouncement;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
1586
|
if ([permissions[@"carPlay"] isEqual:@(YES)]) {
|
|
651
1587
|
options |= UNAuthorizationOptionCarPlay;
|
|
652
1588
|
}
|