react-native-notify-kit 10.5.0 → 10.7.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 +107 -1
- package/android/src/main/java/app/notifee/core/Notifee.java +9 -0
- package/android/src/main/java/app/notifee/core/ReceiverService.java +41 -4
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidStyleModel.java +63 -34
- package/android/src/main/java/app/notifee/core/utility/FullScreenIntentUtils.java +53 -0
- package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +15 -1
- package/android/src/test/java/app/notifee/core/ReceiverServicePendingIntentIdentityTest.java +303 -0
- package/android/src/test/java/app/notifee/core/model/NotificationAndroidStyleModelPersonFailureTest.java +337 -0
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +27 -70
- package/android/src/test/java/app/notifee/core/utility/FullScreenIntentUtilsTest.java +83 -0
- package/android/src/test/java/app/notifee/core/utility/ResourceUtilsBitmapOwnershipTest.java +145 -0
- package/dist/NotifeeApiModule.js +4 -0
- package/dist/NotifeeApiModule.js.map +1 -1
- package/dist/types/Notification.d.ts +2 -1
- package/dist/types/Notification.js.map +1 -1
- package/dist/types/NotificationAndroid.d.ts +17 -5
- package/dist/types/NotificationAndroid.js.map +1 -1
- package/dist/validators/validateAndroidNotification.js +4 -0
- package/dist/validators/validateAndroidNotification.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/NotifeeCore/NotifeeCoreExtensionHelper.m +285 -91
- package/ios/NotifeeCore/NotifeeCoreUtil.m +159 -13
- package/jest-mock.js +1 -0
- package/package.json +4 -1
- package/plugin/build/android/withNotifyKitAndroidNotificationIcons.js +498 -0
- package/plugin/build/index.js +13 -18
- package/plugin/build/options.js +84 -0
- package/server/dist/validation.d.ts.map +1 -1
- package/server/dist/validation.js +14 -0
- package/server/dist/validation.js.map +1 -1
- package/server/src/validation.ts +20 -0
- package/src/NotifeeApiModule.ts +4 -0
- package/src/types/Notification.ts +2 -1
- package/src/types/NotificationAndroid.ts +18 -5
- package/src/validators/validateAndroidNotification.ts +7 -0
- package/src/version.ts +1 -1
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
#include <CoreGraphics/CGGeometry.h>
|
|
20
20
|
#import <Intents/INIntentIdentifiers.h>
|
|
21
21
|
#import <UIKit/UIKit.h>
|
|
22
|
+
#import <dispatch/dispatch.h>
|
|
22
23
|
#include <limits.h>
|
|
23
24
|
#include <math.h>
|
|
24
25
|
#import "NotifeeCore+NSURLSession.h"
|
|
@@ -55,9 +56,30 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
|
|
|
55
56
|
defaultMissingCreatedAt:(BOOL)defaultMissingCreatedAt;
|
|
56
57
|
+ (nullable id)rollingJSONObjectFromObject:(nullable id)object;
|
|
57
58
|
+ (NSNumber *)rollingCurrentTimestampMs;
|
|
59
|
+
+ (INSendMessageIntent *)generateSenderIntentForCommunicationNotification:
|
|
60
|
+
(NSDictionary *)communicationInfo
|
|
61
|
+
deadline:(dispatch_time_t)deadline;
|
|
62
|
+
+ (dispatch_time_t)communicationAvatarCurrentTime;
|
|
63
|
+
|
|
64
|
+
@end
|
|
65
|
+
|
|
66
|
+
@interface NotifeeCoreCommunicationAvatarDownloadResult : NSObject
|
|
67
|
+
|
|
68
|
+
@property(nonatomic, strong, nullable) NSURL *URL;
|
|
69
|
+
@property(nonatomic, assign) dispatch_time_t completionTime;
|
|
70
|
+
@property(nonatomic, assign, getter=isCompleted) BOOL completed;
|
|
71
|
+
@property(nonatomic, assign, getter=isUsable) BOOL usable;
|
|
58
72
|
|
|
59
73
|
@end
|
|
60
74
|
|
|
75
|
+
@implementation NotifeeCoreCommunicationAvatarDownloadResult
|
|
76
|
+
@end
|
|
77
|
+
|
|
78
|
+
static BOOL NotifeeCoreIsRemoteURLString(id value) {
|
|
79
|
+
return [value isKindOfClass:NSString.class] &&
|
|
80
|
+
([value hasPrefix:@"http://"] || [value hasPrefix:@"https://"]);
|
|
81
|
+
}
|
|
82
|
+
|
|
61
83
|
@implementation NotifeeCoreUtil
|
|
62
84
|
|
|
63
85
|
+ (NSNumber *)numberForUNNotificationSetting:(UNNotificationSetting)setting {
|
|
@@ -223,20 +245,26 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
|
|
|
223
245
|
* @return NSURL
|
|
224
246
|
*/
|
|
225
247
|
+ (NSURL *)getURLFromString:(NSString *)urlString {
|
|
226
|
-
|
|
248
|
+
if (![urlString isKindOfClass:NSString.class] || [urlString length] == 0) {
|
|
249
|
+
return nil;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
NSURL *parsedURL = [NSURL URLWithString:urlString];
|
|
253
|
+
|
|
254
|
+
if ([parsedURL isFileURL]) {
|
|
255
|
+
return parsedURL;
|
|
256
|
+
}
|
|
227
257
|
|
|
228
|
-
if (
|
|
258
|
+
if (NotifeeCoreIsRemoteURLString(urlString)) {
|
|
229
259
|
// handle remote url by attempting to download attachement synchronously
|
|
230
|
-
|
|
260
|
+
return [self downloadMediaSynchronously:urlString];
|
|
231
261
|
} else if ([urlString hasPrefix:@"/"]) {
|
|
232
262
|
// handle absolute file path
|
|
233
|
-
|
|
234
|
-
} else {
|
|
235
|
-
// try to resolve local resource
|
|
236
|
-
url = [[NSBundle mainBundle] URLForResource:urlString withExtension:nil];
|
|
263
|
+
return [NSURL fileURLWithPath:urlString];
|
|
237
264
|
}
|
|
238
265
|
|
|
239
|
-
|
|
266
|
+
// try to resolve local resource
|
|
267
|
+
return [[NSBundle mainBundle] URLForResource:urlString withExtension:nil];
|
|
240
268
|
}
|
|
241
269
|
|
|
242
270
|
/*
|
|
@@ -1251,16 +1279,135 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
|
|
|
1251
1279
|
|
|
1252
1280
|
+ (INSendMessageIntent *)generateSenderIntentForCommunicationNotification:
|
|
1253
1281
|
(NSDictionary *)communicationInfo {
|
|
1282
|
+
return [self generateSenderIntentForCommunicationNotification:communicationInfo
|
|
1283
|
+
deadline:DISPATCH_TIME_FOREVER];
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
+ (dispatch_time_t)communicationAvatarCurrentTime {
|
|
1287
|
+
return dispatch_time(DISPATCH_TIME_NOW, 0);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
+ (INSendMessageIntent *)
|
|
1291
|
+
generateSenderIntentForCommunicationNotification:(NSDictionary *)communicationInfo
|
|
1292
|
+
deadline:(dispatch_time_t)deadline {
|
|
1254
1293
|
if (@available(iOS 15.0, *)) {
|
|
1255
1294
|
NSDictionary *sender = communicationInfo[@"sender"];
|
|
1256
1295
|
INPersonHandle *senderPersonHandle =
|
|
1257
1296
|
[[INPersonHandle alloc] initWithValue:sender[@"id"] type:INPersonHandleTypeUnknown];
|
|
1258
1297
|
|
|
1298
|
+
id senderAvatarValue = sender[@"avatar"];
|
|
1299
|
+
id groupAvatarValue = communicationInfo[@"groupAvatar"];
|
|
1300
|
+
BOOL sharesAvatar = [senderAvatarValue isKindOfClass:NSString.class] &&
|
|
1301
|
+
[groupAvatarValue isKindOfClass:NSString.class] &&
|
|
1302
|
+
[senderAvatarValue isEqualToString:groupAvatarValue];
|
|
1303
|
+
|
|
1304
|
+
NSURL *senderAvatarURL = nil;
|
|
1305
|
+
NSURL *groupAvatarURL = nil;
|
|
1306
|
+
|
|
1307
|
+
if (deadline == DISPATCH_TIME_FOREVER) {
|
|
1308
|
+
__block NSURL *downloadedGroupAvatarURL = nil;
|
|
1309
|
+
dispatch_group_t groupAvatarDownload = nil;
|
|
1310
|
+
|
|
1311
|
+
if (!sharesAvatar && NotifeeCoreIsRemoteURLString(groupAvatarValue)) {
|
|
1312
|
+
groupAvatarDownload = dispatch_group_create();
|
|
1313
|
+
dispatch_group_async(groupAvatarDownload, dispatch_get_global_queue(QOS_CLASS_UTILITY, 0),
|
|
1314
|
+
^{
|
|
1315
|
+
downloadedGroupAvatarURL = [self getURLFromString:groupAvatarValue];
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
if (senderAvatarValue != nil) {
|
|
1320
|
+
senderAvatarURL = [self getURLFromString:senderAvatarValue];
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
if (sharesAvatar) {
|
|
1324
|
+
groupAvatarURL = senderAvatarURL;
|
|
1325
|
+
} else if (groupAvatarDownload != nil) {
|
|
1326
|
+
if (dispatch_group_wait(groupAvatarDownload, deadline) == 0) {
|
|
1327
|
+
groupAvatarURL = downloadedGroupAvatarURL;
|
|
1328
|
+
}
|
|
1329
|
+
} else if (groupAvatarValue != nil) {
|
|
1330
|
+
groupAvatarURL = [self getURLFromString:groupAvatarValue];
|
|
1331
|
+
}
|
|
1332
|
+
} else {
|
|
1333
|
+
BOOL senderAvatarIsRemote = NotifeeCoreIsRemoteURLString(senderAvatarValue);
|
|
1334
|
+
BOOL groupAvatarIsRemote = NotifeeCoreIsRemoteURLString(groupAvatarValue);
|
|
1335
|
+
BOOL remoteDownloadsMayStart = [self communicationAvatarCurrentTime] < deadline;
|
|
1336
|
+
NotifeeCoreCommunicationAvatarDownloadResult *senderAvatarResult = nil;
|
|
1337
|
+
NotifeeCoreCommunicationAvatarDownloadResult *groupAvatarResult = nil;
|
|
1338
|
+
dispatch_group_t senderAvatarDownload = nil;
|
|
1339
|
+
dispatch_group_t groupAvatarDownload = nil;
|
|
1340
|
+
|
|
1341
|
+
dispatch_group_t (^startRemoteDownload)(NSString *,
|
|
1342
|
+
NotifeeCoreCommunicationAvatarDownloadResult *) =
|
|
1343
|
+
^dispatch_group_t(NSString *avatarValue,
|
|
1344
|
+
NotifeeCoreCommunicationAvatarDownloadResult *result) {
|
|
1345
|
+
dispatch_group_t download = dispatch_group_create();
|
|
1346
|
+
dispatch_group_async(download, dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
|
|
1347
|
+
dispatch_time_t downloadStartTime = [self communicationAvatarCurrentTime];
|
|
1348
|
+
if (downloadStartTime >= deadline) {
|
|
1349
|
+
@synchronized(result) {
|
|
1350
|
+
result.completionTime = downloadStartTime;
|
|
1351
|
+
result.completed = YES;
|
|
1352
|
+
result.usable = NO;
|
|
1353
|
+
}
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
NSURL *downloadedURL = [self getURLFromString:avatarValue];
|
|
1358
|
+
dispatch_time_t completionTime = [self communicationAvatarCurrentTime];
|
|
1359
|
+
@synchronized(result) {
|
|
1360
|
+
result.URL = downloadedURL;
|
|
1361
|
+
result.completionTime = completionTime;
|
|
1362
|
+
result.completed = YES;
|
|
1363
|
+
result.usable = completionTime < deadline;
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
return download;
|
|
1367
|
+
};
|
|
1368
|
+
|
|
1369
|
+
NSURL * (^waitForRemoteDownload)(dispatch_group_t,
|
|
1370
|
+
NotifeeCoreCommunicationAvatarDownloadResult *) =
|
|
1371
|
+
^NSURL *(dispatch_group_t download,
|
|
1372
|
+
NotifeeCoreCommunicationAvatarDownloadResult *result) {
|
|
1373
|
+
dispatch_group_wait(download, deadline);
|
|
1374
|
+
@synchronized(result) {
|
|
1375
|
+
if (result.isCompleted && result.isUsable) {
|
|
1376
|
+
return result.URL;
|
|
1377
|
+
}
|
|
1378
|
+
return nil;
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
if (remoteDownloadsMayStart && senderAvatarIsRemote) {
|
|
1383
|
+
senderAvatarResult = [NotifeeCoreCommunicationAvatarDownloadResult new];
|
|
1384
|
+
senderAvatarDownload = startRemoteDownload(senderAvatarValue, senderAvatarResult);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
if (remoteDownloadsMayStart && !sharesAvatar && groupAvatarIsRemote) {
|
|
1388
|
+
groupAvatarResult = [NotifeeCoreCommunicationAvatarDownloadResult new];
|
|
1389
|
+
groupAvatarDownload = startRemoteDownload(groupAvatarValue, groupAvatarResult);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
if (senderAvatarDownload != nil) {
|
|
1393
|
+
senderAvatarURL = waitForRemoteDownload(senderAvatarDownload, senderAvatarResult);
|
|
1394
|
+
} else if (!senderAvatarIsRemote && senderAvatarValue != nil) {
|
|
1395
|
+
senderAvatarURL = [self getURLFromString:senderAvatarValue];
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
if (sharesAvatar) {
|
|
1399
|
+
groupAvatarURL = senderAvatarURL;
|
|
1400
|
+
} else if (groupAvatarDownload != nil) {
|
|
1401
|
+
groupAvatarURL = waitForRemoteDownload(groupAvatarDownload, groupAvatarResult);
|
|
1402
|
+
} else if (!groupAvatarIsRemote && groupAvatarValue != nil) {
|
|
1403
|
+
groupAvatarURL = [self getURLFromString:groupAvatarValue];
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1259
1407
|
// Parse sender's avatar
|
|
1260
1408
|
INImage *avatar = nil;
|
|
1261
|
-
if (
|
|
1262
|
-
|
|
1263
|
-
avatar = [INImage imageWithURL:url];
|
|
1409
|
+
if (senderAvatarURL != nil) {
|
|
1410
|
+
avatar = [INImage imageWithURL:senderAvatarURL];
|
|
1264
1411
|
}
|
|
1265
1412
|
|
|
1266
1413
|
INPerson *senderPerson = [[INPerson alloc] initWithPersonHandle:senderPersonHandle
|
|
@@ -1305,8 +1452,7 @@ static NSInteger const kNotifeeRollingTargetPerTrigger = 32;
|
|
|
1305
1452
|
sender:senderPerson
|
|
1306
1453
|
attachments:nil];
|
|
1307
1454
|
|
|
1308
|
-
if (
|
|
1309
|
-
NSURL *groupAvatarURL = [[NSURL alloc] initWithString:communicationInfo[@"groupAvatar"]];
|
|
1455
|
+
if (groupAvatarURL != nil) {
|
|
1310
1456
|
INImage *groupAvatarImage = [INImage imageWithURL:groupAvatarURL];
|
|
1311
1457
|
|
|
1312
1458
|
[intent setImage:groupAvatarImage forParameterNamed:@"speakableGroupName"];
|
package/jest-mock.js
CHANGED
|
@@ -83,6 +83,7 @@ export const testNotificationSettings = {
|
|
|
83
83
|
authorizationStatus: Notification.AuthorizationStatus.AUTHORIZED,
|
|
84
84
|
android: {
|
|
85
85
|
alarm: NotificationAndroid.AndroidNotificationSetting.ENABLED,
|
|
86
|
+
fullScreenIntent: NotificationAndroid.AndroidNotificationSetting.ENABLED,
|
|
86
87
|
},
|
|
87
88
|
ios: {
|
|
88
89
|
alert: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-notify-kit",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.7.0",
|
|
4
4
|
"author": "Marco Crupi",
|
|
5
5
|
"description": "Maintained Notifee-compatible React Native notifications library for Android, iOS, FCM Mode, rich notifications, foreground services, and Expo CNG development builds.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
"format:ios": "npm_config_yes=true npx clang-format -i --glob=\"ios/**/*.{h,cpp,m,mm}\" --style=Google",
|
|
41
41
|
"format:ios:check": "npm_config_yes=true npx clang-format --glob=\"ios/**/*.{h,cpp,m,mm}\" --style=Google -n -Werror"
|
|
42
42
|
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@expo/image-utils": "^0.8.14"
|
|
45
|
+
},
|
|
43
46
|
"devDependencies": {
|
|
44
47
|
"@babel/preset-env": "^7.25.3",
|
|
45
48
|
"@babel/runtime": "^7.25.0",
|