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.
- package/cli/dist/templates/templates/NotificationService.swift.tmpl +33 -6
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +6 -0
- package/ios/NotifeeCore/NotifeeCore+NSURLSession.m +20 -3
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +95 -20
- package/ios/NotifeeCore/NotifeeCore.m +15 -1
- package/ios/NotifeeCore/NotifeeCoreExtensionHelper.h +2 -2
- package/ios/NotifeeCore/NotifeeCoreExtensionHelper.m +138 -32
- package/ios/NotifeeCore/NotifeeCoreUtil.m +13 -5
- package/ios/RNNotifee/NotifeeApiModule.mm +7 -0
- package/package.json +2 -2
- package/src/version.ts +1 -1
|
@@ -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 =
|
|
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 =
|
|
50
|
+
guard let bestAttemptContent = mutableContent else {
|
|
43
51
|
nseLog("mutableCopy failed for id=\(request.identifier); delivering original content")
|
|
44
|
-
|
|
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?.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
export declare const version = "10.3.3";
|
package/dist/version.js
CHANGED
|
@@ -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:[
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
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,
|
|
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
|
-
@
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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
|
-
- (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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.
|
|
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 &&
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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 ([
|
|
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 =
|
|
275
|
+
NSString *fileExtension =
|
|
276
|
+
[NotifeeCoreNSURLSession fileExtensionFromSuggestedFilename:suggestedFilename];
|
|
270
277
|
|
|
271
|
-
if (
|
|
278
|
+
if (fileExtension.length == 0) {
|
|
272
279
|
NSLog(@"NotifeeCore: Failed to determine file extension for attachment "
|
|
273
|
-
@"with URL
|
|
274
|
-
urlString,
|
|
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.
|
|
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
|
|
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.
|
|
2
|
+
export const version = '10.3.3';
|