react-native-notify-kit 10.3.1 → 10.3.3

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.
@@ -23,13 +23,21 @@ private func requestedAttachmentURLs(from userInfo: [AnyHashable: Any]) -> [Stri
23
23
  class NotificationService: UNNotificationServiceExtension {
24
24
  var contentHandler: ((UNNotificationContent) -> Void)?
25
25
  var bestAttemptContent: UNMutableNotificationContent?
26
+ private let deliveryLock = NSLock()
27
+ private var didDeliver = false
26
28
 
27
29
  override func didReceive(
28
30
  _ request: UNNotificationRequest,
29
31
  withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
30
32
  ) {
33
+ let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent
34
+
35
+ deliveryLock.lock()
36
+ didDeliver = false
31
37
  self.contentHandler = contentHandler
32
- self.bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent
38
+ self.bestAttemptContent = mutableContent
39
+ deliveryLock.unlock()
40
+
33
41
  let requestedAttachmentUrls = requestedAttachmentURLs(from: request.content.userInfo)
34
42
 
35
43
  nseLog(
@@ -39,9 +47,9 @@ class NotificationService: UNNotificationServiceExtension {
39
47
  "urls=\(requestedAttachmentUrls.joined(separator: ","))"
40
48
  )
41
49
 
42
- guard let bestAttemptContent = bestAttemptContent else {
50
+ guard let bestAttemptContent = mutableContent else {
43
51
  nseLog("mutableCopy failed for id=\(request.identifier); delivering original content")
44
- contentHandler(request.content)
52
+ deliverOnce(request.content)
45
53
  return
46
54
  }
47
55
 
@@ -55,19 +63,38 @@ class NotificationService: UNNotificationServiceExtension {
55
63
  "deliveredAttachments=\(content.attachments.count) " +
56
64
  "identifiers=\(deliveredAttachmentIds)"
57
65
  )
58
- self?.contentHandler?(content)
66
+ self?.deliverOnce(content)
59
67
  }
60
68
  )
61
69
  }
62
70
 
71
+ private func deliverOnce(_ content: UNNotificationContent) {
72
+ var handler: ((UNNotificationContent) -> Void)?
73
+
74
+ deliveryLock.lock()
75
+ if !didDeliver {
76
+ didDeliver = true
77
+ handler = contentHandler
78
+ contentHandler = nil
79
+ bestAttemptContent = nil
80
+ }
81
+ deliveryLock.unlock()
82
+
83
+ handler?(content)
84
+ }
85
+
63
86
  override func serviceExtensionTimeWillExpire() {
64
- if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
87
+ deliveryLock.lock()
88
+ let content = bestAttemptContent
89
+ deliveryLock.unlock()
90
+
91
+ if let bestAttemptContent = content {
65
92
  nseLog(
66
93
  "serviceExtensionTimeWillExpire id=\(bestAttemptContent.userInfo["gcm.message_id"] ?? "n/a") " +
67
94
  "title=\(bestAttemptContent.title) " +
68
95
  "deliveredAttachments=\(bestAttemptContent.attachments.count)"
69
96
  )
70
- contentHandler(bestAttemptContent)
97
+ deliverOnce(bestAttemptContent)
71
98
  }
72
99
  }
73
100
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "10.3.1";
1
+ export declare const version = "10.3.3";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated by genversion.
2
- export const version = '10.3.1';
2
+ export const version = '10.3.3';
3
3
  //# sourceMappingURL=version.js.map
@@ -24,6 +24,10 @@
24
24
  + (void)topUpRollingTimestampTriggersWithCompletion:(void (^)(NSError *error))completion;
25
25
  @end
26
26
 
27
+ @interface NotifeeCoreUNUserNotificationCenter (Rechain)
28
+ - (void)rechainUserNotificationCenterDelegate;
29
+ @end
30
+
27
31
  @implementation NotifeeCoreNSNotificationCenter
28
32
 
29
33
  + (instancetype)instance {
@@ -75,6 +79,8 @@
75
79
  }
76
80
 
77
81
  - (void)application_didBecomeActiveNotification:(nonnull NSNotification *)notification {
82
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
83
+
78
84
  [NotifeeCore topUpRollingTimestampTriggersWithCompletion:^(NSError *error) {
79
85
  if (error != nil) {
80
86
  NSLog(@"NotifeeCore: Failed to top up rolling timestamp triggers after app became active: %@",
@@ -18,18 +18,35 @@
18
18
  #import "NotifeeCore+NSURLSession.h"
19
19
  #import "NotifeeCoreDownloadDelegate.h"
20
20
 
21
+ static NSTimeInterval const kNotifeeAttachmentDownloadTimeoutInterval = 25.0;
22
+
21
23
  @implementation NotifeeCoreNSURLSession
22
24
 
25
+ + (NSURLSessionConfiguration *)attachmentDownloadSessionConfiguration {
26
+ NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
27
+ config.timeoutIntervalForRequest = kNotifeeAttachmentDownloadTimeoutInterval;
28
+ config.timeoutIntervalForResource = kNotifeeAttachmentDownloadTimeoutInterval;
29
+ return config;
30
+ }
31
+
32
+ + (nullable NSString *)fileExtensionFromSuggestedFilename:(nullable NSString *)suggestedFilename {
33
+ NSString *suggestedPathExtension = [suggestedFilename pathExtension];
34
+ if (suggestedPathExtension.length == 0) {
35
+ return nil;
36
+ }
37
+
38
+ return [NSString stringWithFormat:@".%@", suggestedPathExtension];
39
+ }
40
+
23
41
  + (NSString *)downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath error:(NSError **)error {
24
42
  NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
43
+ request.timeoutInterval = kNotifeeAttachmentDownloadTimeoutInterval;
25
44
 
26
45
  NotifeeCoreDownloadDelegate *delegate =
27
46
  [[NotifeeCoreDownloadDelegate alloc] initWithFilePath:localPath];
28
47
 
29
- // The session is created with the defaultSessionConfiguration
30
- // default timeoutIntervalForRequest is 60 seconds.
31
48
  NSURLSession *session =
32
- [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
49
+ [NSURLSession sessionWithConfiguration:[self attachmentDownloadSessionConfiguration]
33
50
  delegate:delegate
34
51
  delegateQueue:nil];
35
52
 
@@ -21,10 +21,63 @@
21
21
  #import "NotifeeCoreDelegateHolder.h"
22
22
  #import "NotifeeCoreUtil.h"
23
23
 
24
+ typedef void (^NotifeeCorePresentationCompletionHandler)(UNNotificationPresentationOptions options);
25
+ typedef void (^NotifeeCoreVoidCompletionHandler)(void);
26
+
24
27
  @interface NotifeeCore (RollingTimestampTopUp)
25
28
  + (void)topUpRollingTimestampTriggersWithCompletion:(void (^)(NSError *error))completion;
26
29
  @end
27
30
 
31
+ @interface NotifeeCoreUNUserNotificationCenter ()
32
+ - (void)refreshOriginalDelegateSelectorFlags;
33
+ - (void)rechainUserNotificationCenterDelegate;
34
+ @end
35
+
36
+ static NotifeeCorePresentationCompletionHandler NotifeeCoreOneShotPresentationCompletionHandler(
37
+ NotifeeCorePresentationCompletionHandler completionHandler) {
38
+ NSObject *completionLock = [NSObject new];
39
+ __block BOOL completionCalled = NO;
40
+
41
+ NotifeeCorePresentationCompletionHandler oneShotCompletionHandler =
42
+ ^(UNNotificationPresentationOptions options) {
43
+ BOOL shouldCallCompletion = NO;
44
+ @synchronized(completionLock) {
45
+ if (!completionCalled) {
46
+ completionCalled = YES;
47
+ shouldCallCompletion = YES;
48
+ }
49
+ }
50
+
51
+ if (shouldCallCompletion && completionHandler != nil) {
52
+ completionHandler(options);
53
+ }
54
+ };
55
+
56
+ return [oneShotCompletionHandler copy];
57
+ }
58
+
59
+ static NotifeeCoreVoidCompletionHandler NotifeeCoreOneShotVoidCompletionHandler(
60
+ NotifeeCoreVoidCompletionHandler completionHandler) {
61
+ NSObject *completionLock = [NSObject new];
62
+ __block BOOL completionCalled = NO;
63
+
64
+ NotifeeCoreVoidCompletionHandler oneShotCompletionHandler = ^{
65
+ BOOL shouldCallCompletion = NO;
66
+ @synchronized(completionLock) {
67
+ if (!completionCalled) {
68
+ completionCalled = YES;
69
+ shouldCallCompletion = YES;
70
+ }
71
+ }
72
+
73
+ if (shouldCallCompletion && completionHandler != nil) {
74
+ completionHandler();
75
+ }
76
+ };
77
+
78
+ return [oneShotCompletionHandler copy];
79
+ }
80
+
28
81
  @implementation NotifeeCoreUNUserNotificationCenter
29
82
 
30
83
  struct {
@@ -47,25 +100,41 @@ struct {
47
100
  }
48
101
 
49
102
  - (void)observe {
50
- static dispatch_once_t once;
51
- __weak NotifeeCoreUNUserNotificationCenter *weakSelf = self;
52
- dispatch_once(&once, ^{
53
- NotifeeCoreUNUserNotificationCenter *strongSelf = weakSelf;
54
- UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
55
- if (center.delegate != nil) {
56
- _originalDelegate = center.delegate;
57
- originalUNCDelegateRespondsTo.openSettingsForNotification = (unsigned int)[_originalDelegate
58
- respondsToSelector:@selector(userNotificationCenter:openSettingsForNotification:)];
59
- originalUNCDelegateRespondsTo.willPresentNotification = (unsigned int)[_originalDelegate
103
+ [self rechainUserNotificationCenterDelegate];
104
+ }
105
+
106
+ - (void)refreshOriginalDelegateSelectorFlags {
107
+ id<UNUserNotificationCenterDelegate> originalDelegate = self.originalDelegate;
108
+
109
+ originalUNCDelegateRespondsTo.openSettingsForNotification =
110
+ originalDelegate != nil &&
111
+ [originalDelegate respondsToSelector:@selector(userNotificationCenter:
112
+ openSettingsForNotification:)];
113
+ originalUNCDelegateRespondsTo.willPresentNotification =
114
+ originalDelegate != nil &&
115
+ [originalDelegate respondsToSelector:@selector
116
+ (userNotificationCenter:willPresentNotification:withCompletionHandler:)];
117
+ originalUNCDelegateRespondsTo.didReceiveNotificationResponse =
118
+ originalDelegate != nil &&
119
+ [originalDelegate
60
120
  respondsToSelector:@selector(userNotificationCenter:
61
- willPresentNotification:withCompletionHandler:)];
62
- originalUNCDelegateRespondsTo.didReceiveNotificationResponse =
63
- (unsigned int)[_originalDelegate
64
- respondsToSelector:@selector(userNotificationCenter:
65
- didReceiveNotificationResponse:withCompletionHandler:)];
121
+ didReceiveNotificationResponse:withCompletionHandler:)];
122
+ }
123
+
124
+ - (void)rechainUserNotificationCenterDelegate {
125
+ @synchronized(self) {
126
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
127
+ id<UNUserNotificationCenterDelegate> currentDelegate = center.delegate;
128
+
129
+ if (currentDelegate == self) {
130
+ [self refreshOriginalDelegateSelectorFlags];
131
+ return;
66
132
  }
67
- center.delegate = strongSelf;
68
- });
133
+
134
+ self.originalDelegate = currentDelegate;
135
+ [self refreshOriginalDelegateSelectorFlags];
136
+ center.delegate = self;
137
+ }
69
138
  }
70
139
 
71
140
  - (void)markInitialNotificationGathered {
@@ -176,9 +245,11 @@ struct {
176
245
  }
177
246
 
178
247
  } else if (_originalDelegate != nil && originalUNCDelegateRespondsTo.willPresentNotification) {
248
+ NotifeeCorePresentationCompletionHandler oneShotCompletionHandler =
249
+ NotifeeCoreOneShotPresentationCompletionHandler(completionHandler);
179
250
  [_originalDelegate userNotificationCenter:center
180
251
  willPresentNotification:notification
181
- withCompletionHandler:completionHandler];
252
+ withCompletionHandler:oneShotCompletionHandler];
182
253
  } else {
183
254
  // No original delegate captured and the notification is not Notifee-owned.
184
255
  // Returning UNNotificationPresentationOptionNone would silently drop the
@@ -214,9 +285,11 @@ struct {
214
285
  // Flag OFF: always forward to original delegate, never parse as Notifee
215
286
  if (_originalDelegate != nil &&
216
287
  originalUNCDelegateRespondsTo.didReceiveNotificationResponse) {
288
+ NotifeeCoreVoidCompletionHandler oneShotCompletionHandler =
289
+ NotifeeCoreOneShotVoidCompletionHandler(completionHandler);
217
290
  [_originalDelegate userNotificationCenter:center
218
291
  didReceiveNotificationResponse:response
219
- withCompletionHandler:completionHandler];
292
+ withCompletionHandler:oneShotCompletionHandler];
220
293
  } else {
221
294
  completionHandler();
222
295
  }
@@ -224,9 +297,11 @@ struct {
224
297
  }
225
298
  // Flag ON (default): existing behavior
226
299
  if (_originalDelegate != nil && originalUNCDelegateRespondsTo.didReceiveNotificationResponse) {
300
+ NotifeeCoreVoidCompletionHandler oneShotCompletionHandler =
301
+ NotifeeCoreOneShotVoidCompletionHandler(completionHandler);
227
302
  [_originalDelegate userNotificationCenter:center
228
303
  didReceiveNotificationResponse:response
229
- withCompletionHandler:completionHandler];
304
+ withCompletionHandler:oneShotCompletionHandler];
230
305
  return;
231
306
  } else {
232
307
  notifeeNotification =
@@ -26,6 +26,10 @@
26
26
  #import "NotifeeCoreExtensionHelper.h"
27
27
  #import "NotifeeCoreUtil.h"
28
28
 
29
+ @interface NotifeeCoreUNUserNotificationCenter (Rechain)
30
+ - (void)rechainUserNotificationCenterDelegate;
31
+ @end
32
+
29
33
  static NSString *const kNotifeeRollingPublicId = @"notifee_rolling_public_id";
30
34
  static NSString *const kNotifeeRollingOccurrenceMs = @"notifee_rolling_occurrence_ms";
31
35
  static NSString *const kNotifeeRollingInternalId = @"notifee_rolling_internal_id";
@@ -1140,6 +1144,8 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1140
1144
  * @param block notifeeMethodVoidBlock
1141
1145
  */
1142
1146
  + (void)displayNotification:(NSDictionary *)notification withBlock:(notifeeMethodVoidBlock)block {
1147
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
1148
+
1143
1149
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1144
1150
  UNMutableNotificationContent *content = [self buildNotificationContent:notification
1145
1151
  withTrigger:nil];
@@ -1191,7 +1197,8 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1191
1197
  dispatch_async(dispatch_get_main_queue(), ^{
1192
1198
  BOOL isApplicationActive = NO;
1193
1199
  if (![NotifeeCoreUtil isAppExtension]) {
1194
- UIApplication *application = [NotifeeCoreUtil notifeeUIApplication];
1200
+ UIApplication *application =
1201
+ (UIApplication *)[NotifeeCoreUtil notifeeUIApplication];
1195
1202
  if (application != nil) {
1196
1203
  isApplicationActive =
1197
1204
  application.applicationState == UIApplicationStateActive;
@@ -1222,6 +1229,8 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1222
1229
  + (void)createTriggerNotification:(NSDictionary *)notification
1223
1230
  withTrigger:(NSDictionary *)trigger
1224
1231
  withBlock:(notifeeMethodVoidBlock)block {
1232
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
1233
+
1225
1234
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1226
1235
  UNMutableNotificationContent *content =
1227
1236
  [self triggerNotificationContentForNotification:notification trigger:trigger];
@@ -1542,6 +1551,8 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1542
1551
  */
1543
1552
  + (void)requestPermission:(NSDictionary *)permissions
1544
1553
  withBlock:(notifeeMethodNSDictionaryBlock)block {
1554
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
1555
+
1545
1556
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
1546
1557
 
1547
1558
  UNAuthorizationOptions options = UNAuthorizationOptionNone;
@@ -1677,6 +1688,8 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1677
1688
  }
1678
1689
 
1679
1690
  + (void)getInitialNotification:(notifeeMethodNSDictionaryBlock)block {
1691
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
1692
+
1680
1693
  [NotifeeCoreUNUserNotificationCenter instance].initialNotificationBlock = block;
1681
1694
  [[NotifeeCoreUNUserNotificationCenter instance] getInitialNotification];
1682
1695
  }
@@ -1783,6 +1796,7 @@ typedef NS_ENUM(NSInteger, NotifeeCoreRollingErrorCode) {
1783
1796
  [NotifeeCoreUNUserNotificationCenter instance].shouldHandleRemoteNotifications =
1784
1797
  [config[@"ios"][@"handleRemoteNotifications"] boolValue];
1785
1798
  }
1799
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
1786
1800
  block(nil);
1787
1801
  }
1788
1802
 
@@ -24,8 +24,8 @@ static NSString *const kPayloadOptionsName = @"notifee_options";
24
24
  static NSString *const kPayloadOptionsImageURLName = @"image";
25
25
 
26
26
  @interface NotifeeCoreExtensionHelper : NSObject
27
- @property(nonatomic, strong) void (^contentHandler)(UNNotificationContent *c);
28
- @property(nonatomic, strong) UNMutableNotificationContent *modifiedContent;
27
+ @property(nonatomic, copy, nullable) void (^contentHandler)(UNNotificationContent *c);
28
+ @property(nonatomic, strong, nullable) UNMutableNotificationContent *modifiedContent;
29
29
 
30
30
  + (NotifeeCoreExtensionHelper *)instance NS_SWIFT_NAME(serviceExtension());
31
31
 
@@ -23,30 +23,56 @@
23
23
  static NSString *const kNoExtension = @"";
24
24
  static NSString *const kImagePathPrefix = @"image/";
25
25
 
26
- @implementation NotifeeCoreExtensionHelper
27
- + (NotifeeCoreExtensionHelper *)instance {
28
- static dispatch_once_t once;
29
- static NotifeeCoreExtensionHelper *instance;
30
- dispatch_once(&once, ^{
31
- instance = [[self alloc] init];
32
- });
26
+ @interface NotifeeCoreExtensionHelper ()
27
+ - (NSMutableDictionary *)parseNotifeeOptions:(id)payload;
28
+ - (void)loadAttachment:(NSDictionary *)attachmentDict
29
+ completionHandler:(void (^)(UNNotificationAttachment *))completionHandler;
30
+ @end
33
31
 
34
- return instance;
35
- }
32
+ @interface NotifeeCoreExtensionRequestContext : NSObject
33
+ @property(nonatomic, strong) NotifeeCoreExtensionHelper *helper;
34
+ @property(nonatomic, copy) void (^contentHandler)(UNNotificationContent *content);
35
+ @property(nonatomic, strong) UNMutableNotificationContent *modifiedContent;
36
+ @property(nonatomic, assign) BOOL notificationDelivered;
36
37
 
37
- - (void)populateNotificationContent:(UNNotificationRequest *_Nullable)request
38
- withContent:(UNMutableNotificationContent *)content
39
- withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
40
- self.contentHandler = [contentHandler copy];
41
- self.modifiedContent = content;
38
+ - (instancetype)initWithHelper:(NotifeeCoreExtensionHelper *)helper
39
+ content:(UNMutableNotificationContent *)content
40
+ contentHandler:(void (^)(UNNotificationContent *content))contentHandler;
41
+ - (void)populateNotificationContentWithRequest:(UNNotificationRequest *_Nullable)request;
42
+ - (void)processCommunicationData:(NSMutableDictionary *)options;
43
+ - (void)handleAttachmentsAndDeliverNotificaiton:(NSMutableDictionary *)options;
44
+ - (void)deliverNotification;
45
+ @end
46
+
47
+ @implementation NotifeeCoreExtensionRequestContext
48
+
49
+ - (instancetype)initWithHelper:(NotifeeCoreExtensionHelper *)helper
50
+ content:(UNMutableNotificationContent *)content
51
+ contentHandler:(void (^)(UNNotificationContent *content))contentHandler {
52
+ self = [super init];
53
+ if (self != nil) {
54
+ self.helper = helper;
55
+ self.contentHandler = [contentHandler copy];
56
+ self.modifiedContent = content;
57
+ self.notificationDelivered = NO;
58
+ }
42
59
 
43
- if (!content.userInfo[@"notifee_options"]) {
60
+ return self;
61
+ }
62
+
63
+ - (void)populateNotificationContentWithRequest:(UNNotificationRequest *_Nullable)request {
64
+ id notifeeOptionsPayload = self.modifiedContent.userInfo[kPayloadOptionsName];
65
+ if (!notifeeOptionsPayload) {
44
66
  [self deliverNotification];
45
67
  return;
46
68
  }
47
69
 
48
- // fcm: apns: { payload: {notifee_options: {} } }
49
- NSMutableDictionary *options = [self.modifiedContent.userInfo[@"notifee_options"] mutableCopy];
70
+ // fcm: apns: { payload: {notifee_options: "{}" } }
71
+ NSMutableDictionary *options = [self.helper parseNotifeeOptions:notifeeOptionsPayload];
72
+ if (options == nil) {
73
+ [self deliverNotification];
74
+ return;
75
+ }
50
76
 
51
77
  options[@"remote"] = @YES;
52
78
 
@@ -60,7 +86,7 @@ static NSString *const kImagePathPrefix = @"image/";
60
86
  options[@"id"] = request.identifier;
61
87
  }
62
88
 
63
- if (options[@"title"] == nil && content.title != nil) {
89
+ if (options[@"title"] == nil && self.modifiedContent.title != nil) {
64
90
  options[@"title"] = self.modifiedContent.title;
65
91
  }
66
92
 
@@ -135,14 +161,100 @@ static NSString *const kImagePathPrefix = @"image/";
135
161
  }
136
162
 
137
163
  // Attempt to download attachment
138
- [self loadAttachment:attachmentDict
139
- completionHandler:^(UNNotificationAttachment *attachment) {
140
- if (attachment != nil) {
141
- self.modifiedContent.attachments = @[ attachment ];
142
- }
143
-
144
- [self deliverNotification];
145
- }];
164
+ [self.helper loadAttachment:attachmentDict
165
+ completionHandler:^(UNNotificationAttachment *attachment) {
166
+ if (attachment != nil) {
167
+ @synchronized(self) {
168
+ if (!self.notificationDelivered && self.modifiedContent != nil) {
169
+ self.modifiedContent.attachments = @[ attachment ];
170
+ }
171
+ }
172
+ }
173
+
174
+ [self deliverNotification];
175
+ }];
176
+ }
177
+
178
+ - (void)deliverNotification {
179
+ void (^contentHandler)(UNNotificationContent *) = nil;
180
+ UNNotificationContent *modifiedContent = nil;
181
+
182
+ @synchronized(self) {
183
+ if (self.notificationDelivered || self.contentHandler == nil) {
184
+ return;
185
+ }
186
+
187
+ contentHandler = [self.contentHandler copy];
188
+ modifiedContent = self.modifiedContent;
189
+ self.notificationDelivered = YES;
190
+ self.contentHandler = nil;
191
+ self.modifiedContent = nil;
192
+ }
193
+
194
+ if (contentHandler != nil && modifiedContent != nil) {
195
+ contentHandler(modifiedContent);
196
+ }
197
+ }
198
+
199
+ @end
200
+
201
+ @implementation NotifeeCoreExtensionHelper
202
+ + (NotifeeCoreExtensionHelper *)instance {
203
+ static dispatch_once_t once;
204
+ static NotifeeCoreExtensionHelper *instance;
205
+ dispatch_once(&once, ^{
206
+ instance = [[self alloc] init];
207
+ });
208
+
209
+ return instance;
210
+ }
211
+
212
+ - (NSMutableDictionary *)parseNotifeeOptions:(id)payload {
213
+ if ([payload isKindOfClass:[NSDictionary class]]) {
214
+ return [payload mutableCopy];
215
+ }
216
+
217
+ if ([payload isKindOfClass:[NSString class]]) {
218
+ NSData *optionsData = [payload dataUsingEncoding:NSUTF8StringEncoding];
219
+ if (optionsData == nil) {
220
+ NSLog(@"NotifeeCoreExtensionHelper: Could not decode notifee_options string as UTF-8");
221
+ return nil;
222
+ }
223
+
224
+ NSError *error = nil;
225
+ id jsonObject = [NSJSONSerialization JSONObjectWithData:optionsData
226
+ options:NSJSONReadingFragmentsAllowed
227
+ error:&error];
228
+
229
+ if (error != nil) {
230
+ NSLog(@"NotifeeCoreExtensionHelper: Could not parse notifee_options JSON: %@", error);
231
+ return nil;
232
+ }
233
+
234
+ if (![jsonObject isKindOfClass:[NSDictionary class]]) {
235
+ NSLog(@"NotifeeCoreExtensionHelper: Ignoring notifee_options JSON because it is not a "
236
+ @"dictionary: %@",
237
+ NSStringFromClass([jsonObject class]));
238
+ return nil;
239
+ }
240
+
241
+ return [jsonObject mutableCopy];
242
+ }
243
+
244
+ NSLog(@"NotifeeCoreExtensionHelper: Ignoring notifee_options because it is not a dictionary "
245
+ @"or JSON string: %@",
246
+ NSStringFromClass([payload class]));
247
+ return nil;
248
+ }
249
+
250
+ - (void)populateNotificationContent:(UNNotificationRequest *_Nullable)request
251
+ withContent:(UNMutableNotificationContent *)content
252
+ withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
253
+ NotifeeCoreExtensionRequestContext *context =
254
+ [[NotifeeCoreExtensionRequestContext alloc] initWithHelper:self
255
+ content:content
256
+ contentHandler:contentHandler];
257
+ [context populateNotificationContentWithRequest:request];
146
258
  }
147
259
 
148
260
  - (NSString *)fileExtensionForResponse:(NSURLResponse *)response {
@@ -220,10 +332,4 @@ static NSString *const kImagePathPrefix = @"image/";
220
332
  }
221
333
  }
222
334
 
223
- - (void)deliverNotification {
224
- if (self.contentHandler) {
225
- self.contentHandler(self.modifiedContent);
226
- }
227
- }
228
-
229
335
  @end
@@ -23,6 +23,12 @@
23
23
  #include <math.h>
24
24
  #import "NotifeeCore+NSURLSession.h"
25
25
 
26
+ @interface NotifeeCoreNSURLSession (NotifeeCoreUtil)
27
+
28
+ + (nullable NSString *)fileExtensionFromSuggestedFilename:(nullable NSString *)suggestedFilename;
29
+
30
+ @end
31
+
26
32
  static NSString *const kNotifeeRollingTimestampTriggersStorageKey =
27
33
  @"app.notifee.core.rollingTimestampTriggers.v1";
28
34
  static NSString *const kNotifeeRollingInternalIdPrefix = @"__notifee_rolling__";
@@ -83,7 +89,7 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
83
89
  notificationActionDict[@"authenticationRequired"] =
84
90
  @(((notificationAction.options & UNNotificationActionOptionAuthenticationRequired) != 0));
85
91
 
86
- if ([[notificationAction class] isKindOfClass:[UNTextInputNotificationAction class]]) {
92
+ if ([notificationAction isKindOfClass:[UNTextInputNotificationAction class]]) {
87
93
  UNTextInputNotificationAction *notificationInputAction =
88
94
  (UNTextInputNotificationAction *)notificationAction;
89
95
  if ([notificationInputAction textInputButtonTitle] == nil &&
@@ -266,12 +272,14 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
266
272
  // Rename the recently downloaded file to include its file extension
267
273
  NSFileManager *fileManager = [NSFileManager defaultManager];
268
274
 
269
- NSString *fileExtension = [NSString stringWithFormat:@".%@", [suggestedFilename pathExtension]];
275
+ NSString *fileExtension =
276
+ [NotifeeCoreNSURLSession fileExtensionFromSuggestedFilename:suggestedFilename];
270
277
 
271
- if (!fileExtension || [fileExtension isEqualToString:@""]) {
278
+ if (fileExtension.length == 0) {
272
279
  NSLog(@"NotifeeCore: Failed to determine file extension for attachment "
273
- @"with URL %@: %@",
274
- urlString, error);
280
+ @"with URL %@ and suggested filename %@",
281
+ urlString, suggestedFilename);
282
+ [fileManager removeItemAtPath:tempDestination error:nil];
275
283
  return nil;
276
284
  }
277
285
 
@@ -18,6 +18,11 @@
18
18
  #import "NotifeeApiModule.h"
19
19
  #import <React/RCTUtils.h>
20
20
  #import <UIKit/UIKit.h>
21
+ #import "NotifeeCore+UNUserNotificationCenter.h"
22
+
23
+ @interface NotifeeCoreUNUserNotificationCenter (Rechain)
24
+ - (void)rechainUserNotificationCenterDelegate;
25
+ @end
21
26
 
22
27
  static NSString *kReactNativeNotifeeNotificationEvent = @"app.notifee.notification-event";
23
28
  static NSString *kReactNativeNotifeeNotificationBackgroundEvent =
@@ -56,6 +61,8 @@ RCT_EXPORT_MODULE();
56
61
  }
57
62
 
58
63
  - (void)startObserving {
64
+ [[NotifeeCoreUNUserNotificationCenter instance] rechainUserNotificationCenterDelegate];
65
+
59
66
  NSArray *eventsToFlush;
60
67
  @synchronized(self) {
61
68
  hasListeners = YES;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-notify-kit",
3
- "version": "10.3.1",
3
+ "version": "10.3.3",
4
4
  "author": "Marco Crupi",
5
5
  "description": "Maintained Notifee-compatible fork for React Native — advanced local notifications for Android & iOS.",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "build:watch": "tsc --watch",
31
31
  "test:server": "jest --config jest.config.server.js",
32
32
  "prepare": "yarn run build",
33
- "prepack": "bash ../../scripts/prepack-cli.sh",
33
+ "prepack": "cd ../.. && bash build_ios_core.sh && bash scripts/verify-ios-core-generation.sh && bash scripts/prepack-cli.sh",
34
34
  "postpack": "rm -rf cli",
35
35
  "prepublishOnly": "cd ../.. && yarn run build:core",
36
36
  "format:android": "google-java-format --replace -i $(find . -type f -name \"*.java\" ! -path \"*/node_modules/*\" ! -path \"*/generated/*\")",
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '10.3.1';
2
+ export const version = '10.3.3';