react-native-notify-kit 10.8.1 → 10.9.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 +33 -18
- package/android/build.gradle +50 -4
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/app/notifee/core/ForegroundService.java +395 -5
- package/android/src/main/java/app/notifee/core/ForegroundServiceRunLimitReceiver.java +15 -0
- package/android/src/main/java/app/notifee/core/ForegroundServiceRunLimitScheduler.java +461 -0
- package/android/src/main/java/app/notifee/core/NotificationManager.java +6 -0
- package/android/src/main/java/app/notifee/core/event/NotificationEvent.java +6 -0
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidModel.java +29 -0
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeEventSubscriber.kt +3 -0
- package/android/src/test/java/app/notifee/core/ForegroundServiceRunLimitTest.java +2357 -0
- package/android/src/test/java/app/notifee/core/ForegroundServiceTest.java +23 -13
- package/android/src/test/java/app/notifee/core/ShadowServiceCompatibilityTest.java +170 -0
- package/android/src/test/resources/robolectric.properties +4 -0
- package/cli/dist/cli.js +0 -1
- package/cli/dist/commands/initNse.js +1 -2
- package/cli/dist/lib/detectProject.js +1 -2
- package/cli/dist/lib/initNseCore.js +0 -1
- package/cli/dist/lib/logger.js +0 -1
- package/cli/dist/lib/patchPodfile.js +0 -1
- package/cli/dist/lib/patchXcodeProject.js +22 -3
- package/cli/dist/lib/writeTemplates.js +0 -1
- package/cli/dist/lib/xcode.js +6 -0
- package/cli/dist/templates/NotificationService.swift.tmpl +74 -6
- package/cli/package.json +1 -0
- package/cli/vendor/xcode/AUTHORS +6 -0
- package/cli/vendor/xcode/LICENSE +202 -0
- package/cli/vendor/xcode/NOTICE +5 -0
- package/cli/vendor/xcode/README.md +32 -0
- package/cli/vendor/xcode/UPSTREAM-SHA256.json +12 -0
- package/cli/vendor/xcode/index.js +18 -0
- package/cli/vendor/xcode/lib/parseJob.js +32 -0
- package/cli/vendor/xcode/lib/parser/pbxproj.js +1904 -0
- package/cli/vendor/xcode/lib/parser/pbxproj.pegjs +280 -0
- package/cli/vendor/xcode/lib/pbxFile.js +233 -0
- package/cli/vendor/xcode/lib/pbxProject.js +2205 -0
- package/cli/vendor/xcode/lib/pbxWriter.js +309 -0
- package/dist/NotifeeNativeModule.web.d.ts +2 -2
- package/dist/types/Notification.d.ts +12 -1
- package/dist/types/Notification.js +3 -0
- package/dist/types/Notification.js.map +1 -1
- package/dist/types/NotificationAndroid.d.ts +9 -0
- package/dist/types/NotificationAndroid.js.map +1 -1
- package/dist/validators/validateAndroidNotification.js +26 -1
- package/dist/validators/validateAndroidNotification.js.map +1 -1
- package/dist/validators/validateAndroidStyle.js +6 -0
- package/dist/validators/validateAndroidStyle.js.map +1 -1
- package/dist/validators/validateIOSAttachment.js +3 -1
- package/dist/validators/validateIOSAttachment.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -5
- package/src/NotifeeNativeModule.web.ts +2 -2
- package/src/types/Notification.ts +13 -0
- package/src/types/NotificationAndroid.ts +10 -0
- package/src/validators/validateAndroidNotification.ts +31 -1
- package/src/validators/validateAndroidStyle.ts +10 -2
- package/src/validators/validateIOSAttachment.ts +5 -1
- package/src/version.ts +1 -1
- package/cli/dist/cli.bundle.js +0 -20834
- package/cli/dist/cli.d.ts +0 -2
- package/cli/dist/cli.js.map +0 -1
- package/cli/dist/commands/initNse.d.ts +0 -12
- package/cli/dist/commands/initNse.js.map +0 -1
- package/cli/dist/lib/detectProject.d.ts +0 -12
- package/cli/dist/lib/detectProject.js.map +0 -1
- package/cli/dist/lib/initNseCore.d.ts +0 -8
- package/cli/dist/lib/initNseCore.js.map +0 -1
- package/cli/dist/lib/logger.d.ts +0 -4
- package/cli/dist/lib/logger.js.map +0 -1
- package/cli/dist/lib/patchPodfile.d.ts +0 -23
- package/cli/dist/lib/patchPodfile.js.map +0 -1
- package/cli/dist/lib/patchXcodeProject.d.ts +0 -41
- package/cli/dist/lib/patchXcodeProject.js.map +0 -1
- package/cli/dist/lib/writeTemplates.d.ts +0 -11
- package/cli/dist/lib/writeTemplates.js.map +0 -1
- package/cli/dist/templates/templates/Info.plist.tmpl +0 -29
- package/cli/dist/templates/templates/NotificationService.swift.tmpl +0 -100
- package/cli/dist/templates/templates/NotifyKitNSE.entitlements.tmpl +0 -6
|
@@ -119,7 +119,7 @@ public class ForegroundServiceTest {
|
|
|
119
119
|
|
|
120
120
|
@Test
|
|
121
121
|
@Config(
|
|
122
|
-
sdk = {34, 35},
|
|
122
|
+
sdk = {34, 35, 37},
|
|
123
123
|
shadows = SliceAShadowService.class)
|
|
124
124
|
public void sliceA_demotionPrecedesDestructiveRetirementAndEventWork() throws Exception {
|
|
125
125
|
ForegroundService service = sliceAService(ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
|
@@ -221,7 +221,9 @@ public class ForegroundServiceTest {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
@Test
|
|
224
|
-
@Config(
|
|
224
|
+
@Config(
|
|
225
|
+
sdk = {35, 37},
|
|
226
|
+
shadows = SliceAShadowService.class)
|
|
225
227
|
public void sliceA_reservedUnknownAndAcceptedUndeliveredStartsRemainHeld() throws Exception {
|
|
226
228
|
ForegroundService service = sliceAService(ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
|
227
229
|
RecordingServiceContext context = useRecordingContext();
|
|
@@ -338,7 +340,9 @@ public class ForegroundServiceTest {
|
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
@Test
|
|
341
|
-
@Config(
|
|
343
|
+
@Config(
|
|
344
|
+
sdk = {35, 37},
|
|
345
|
+
shadows = SliceAShadowService.class)
|
|
342
346
|
public void sliceA_demotionThrowPreservesEvidenceAndPrimaryEvenWhenStopThrows() throws Exception {
|
|
343
347
|
ForegroundService service = sliceAService(ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
|
344
348
|
Object runner = issue81Field(service, "mRunnerToken");
|
|
@@ -1047,7 +1051,8 @@ public class ForegroundServiceTest {
|
|
|
1047
1051
|
}
|
|
1048
1052
|
|
|
1049
1053
|
@Implementation
|
|
1050
|
-
protected void startForeground(int id, Notification notification, int foregroundServiceType)
|
|
1054
|
+
protected void startForeground(int id, Notification notification, int foregroundServiceType)
|
|
1055
|
+
throws Exception {
|
|
1051
1056
|
if (promotionFailure != null) throw promotionFailure;
|
|
1052
1057
|
promotions++;
|
|
1053
1058
|
foreground = true;
|
|
@@ -1272,7 +1277,9 @@ public class ForegroundServiceTest {
|
|
|
1272
1277
|
}
|
|
1273
1278
|
|
|
1274
1279
|
@Test
|
|
1275
|
-
@Config(
|
|
1280
|
+
@Config(
|
|
1281
|
+
sdk = {35, 37},
|
|
1282
|
+
shadows = Issue81ShadowService.class)
|
|
1276
1283
|
public void issue82_pendingB_definiteRejectionReevaluatesRecovery_unknownDoesNot()
|
|
1277
1284
|
throws Exception {
|
|
1278
1285
|
for (RuntimeException reply :
|
|
@@ -1824,7 +1831,7 @@ public class ForegroundServiceTest {
|
|
|
1824
1831
|
|
|
1825
1832
|
@Test
|
|
1826
1833
|
@Config(
|
|
1827
|
-
sdk = {31, 33, 34, 35},
|
|
1834
|
+
sdk = {31, 33, 34, 35, 37},
|
|
1828
1835
|
shadows = Issue81ShadowService.class)
|
|
1829
1836
|
public void issue81_retryFreshDenied_recoversWithoutClaimingPromotion() throws Exception {
|
|
1830
1837
|
issue81AssertFreshRecovery(Service.START_FLAG_RETRY);
|
|
@@ -2030,7 +2037,9 @@ public class ForegroundServiceTest {
|
|
|
2030
2037
|
}
|
|
2031
2038
|
|
|
2032
2039
|
@Test
|
|
2033
|
-
@Config(
|
|
2040
|
+
@Config(
|
|
2041
|
+
sdk = {33, 37},
|
|
2042
|
+
shadows = Issue81ShadowService.class)
|
|
2034
2043
|
public void issue81_deniedA_withQueuedStop_promotesBBeforeStopping() throws Exception {
|
|
2035
2044
|
RecordingServiceContext context = useRecordingContext();
|
|
2036
2045
|
ForegroundService service = issue81Service();
|
|
@@ -2371,7 +2380,7 @@ public class ForegroundServiceTest {
|
|
|
2371
2380
|
|
|
2372
2381
|
@Test
|
|
2373
2382
|
@Config(
|
|
2374
|
-
sdk = {31, 34},
|
|
2383
|
+
sdk = {31, 34, 37},
|
|
2375
2384
|
shadows = Issue81ShadowService.class)
|
|
2376
2385
|
public void issue81_deferredRecovery_lateSecurityRejection_stops() throws Exception {
|
|
2377
2386
|
issue81AssertLateRejection(new SecurityException("B rejected"));
|
|
@@ -3105,7 +3114,7 @@ public class ForegroundServiceTest {
|
|
|
3105
3114
|
}
|
|
3106
3115
|
|
|
3107
3116
|
@Implementation
|
|
3108
|
-
protected void startForeground(int id, Notification notification) {
|
|
3117
|
+
protected void startForeground(int id, Notification notification) throws Exception {
|
|
3109
3118
|
if (!forwardingTyped) {
|
|
3110
3119
|
recordPromotion(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
|
|
3111
3120
|
}
|
|
@@ -3113,7 +3122,7 @@ public class ForegroundServiceTest {
|
|
|
3113
3122
|
}
|
|
3114
3123
|
|
|
3115
3124
|
@Implementation
|
|
3116
|
-
protected void startForeground(int id, Notification notification, int type) {
|
|
3125
|
+
protected void startForeground(int id, Notification notification, int type) throws Exception {
|
|
3117
3126
|
recordPromotion(id, notification, type);
|
|
3118
3127
|
// ShadowService's typed overload delegates to the two-argument shadow. Record only the
|
|
3119
3128
|
// actual platform invocation so the witness cannot count that delegation as a second call.
|
|
@@ -4180,7 +4189,7 @@ public class ForegroundServiceTest {
|
|
|
4180
4189
|
@Implements(Service.class)
|
|
4181
4190
|
public static class DenyOldNotificationShadowService extends ShadowService {
|
|
4182
4191
|
@Implementation
|
|
4183
|
-
protected void startForeground(int id, Notification notification) {
|
|
4192
|
+
protected void startForeground(int id, Notification notification) throws Exception {
|
|
4184
4193
|
if ("B".equals(notification.extras.getString(Notification.EXTRA_TITLE))) {
|
|
4185
4194
|
throw new ForegroundServiceStartNotAllowedException("real old START denied");
|
|
4186
4195
|
}
|
|
@@ -5274,7 +5283,7 @@ public class ForegroundServiceTest {
|
|
|
5274
5283
|
@Implements(Service.class)
|
|
5275
5284
|
public static class RejectBStartForegroundShadowService extends ShadowService {
|
|
5276
5285
|
@Implementation
|
|
5277
|
-
protected void startForeground(int id, Notification notification) {
|
|
5286
|
+
protected void startForeground(int id, Notification notification) throws Exception {
|
|
5278
5287
|
if ("B".equals(notification.extras.getString(Notification.EXTRA_TITLE))) {
|
|
5279
5288
|
throw new SecurityException("posting B rejected");
|
|
5280
5289
|
}
|
|
@@ -5282,7 +5291,8 @@ public class ForegroundServiceTest {
|
|
|
5282
5291
|
}
|
|
5283
5292
|
|
|
5284
5293
|
@Implementation
|
|
5285
|
-
protected void startForeground(int id, Notification notification, int foregroundServiceType)
|
|
5294
|
+
protected void startForeground(int id, Notification notification, int foregroundServiceType)
|
|
5295
|
+
throws Exception {
|
|
5286
5296
|
if ("B".equals(notification.extras.getString(Notification.EXTRA_TITLE))) {
|
|
5287
5297
|
throw new SecurityException("posting B rejected");
|
|
5288
5298
|
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
package app.notifee.core;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertSame;
|
|
5
|
+
import static org.junit.Assert.assertThrows;
|
|
6
|
+
import static org.junit.Assert.assertTrue;
|
|
7
|
+
|
|
8
|
+
import android.app.Notification;
|
|
9
|
+
import android.app.NotificationChannel;
|
|
10
|
+
import android.app.NotificationManager;
|
|
11
|
+
import android.app.Service;
|
|
12
|
+
import android.content.Context;
|
|
13
|
+
import android.content.Intent;
|
|
14
|
+
import android.content.pm.ServiceInfo;
|
|
15
|
+
import android.os.Build;
|
|
16
|
+
import android.os.IBinder;
|
|
17
|
+
import org.junit.Test;
|
|
18
|
+
import org.junit.runner.RunWith;
|
|
19
|
+
import org.robolectric.Robolectric;
|
|
20
|
+
import org.robolectric.RobolectricTestRunner;
|
|
21
|
+
import org.robolectric.RuntimeEnvironment;
|
|
22
|
+
import org.robolectric.annotation.Config;
|
|
23
|
+
import org.robolectric.shadows.ShadowService;
|
|
24
|
+
|
|
25
|
+
/** Exercises the real Robolectric superclass calls, including its checked exception contract. */
|
|
26
|
+
@RunWith(RobolectricTestRunner.class)
|
|
27
|
+
public class ShadowServiceCompatibilityTest {
|
|
28
|
+
public static class TestService extends Service {
|
|
29
|
+
@Override
|
|
30
|
+
public IBinder onBind(Intent intent) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Test
|
|
36
|
+
@Config(
|
|
37
|
+
sdk = {29, 35, 36, 37},
|
|
38
|
+
shadows = ForegroundServiceTest.SliceAShadowService.class)
|
|
39
|
+
public void sliceA_typedForwardingPreservesFailures() {
|
|
40
|
+
ForegroundServiceTest.SliceAShadowService.reset();
|
|
41
|
+
assertForwarding(ForegroundServiceTest.SliceAShadowService.class, true);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Test
|
|
45
|
+
@Config(
|
|
46
|
+
sdk = {24, 35, 36, 37},
|
|
47
|
+
shadows = ForegroundServiceTest.Issue81ShadowService.class)
|
|
48
|
+
public void issue81_untypedForwardingPreservesFailures() {
|
|
49
|
+
resetIssue81();
|
|
50
|
+
assertForwarding(ForegroundServiceTest.Issue81ShadowService.class, false);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
@Config(
|
|
55
|
+
sdk = {29, 35, 36, 37},
|
|
56
|
+
shadows = ForegroundServiceTest.Issue81ShadowService.class)
|
|
57
|
+
public void issue81_typedForwardingResetsDelegationAfterFailure() {
|
|
58
|
+
resetIssue81();
|
|
59
|
+
TestService service = assertForwarding(ForegroundServiceTest.Issue81ShadowService.class, true);
|
|
60
|
+
// One record for each outer typed call, including failed attempts, without double counting.
|
|
61
|
+
assertEquals(4, ForegroundServiceTest.Issue81ShadowService.promotions.size());
|
|
62
|
+
service.startForeground(101, notification());
|
|
63
|
+
assertEquals(5, ForegroundServiceTest.Issue81ShadowService.promotions.size());
|
|
64
|
+
assertEquals(
|
|
65
|
+
Integer.valueOf(101), ForegroundServiceTest.Issue81ShadowService.promotions.get(4));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Test
|
|
69
|
+
@Config(
|
|
70
|
+
sdk = {24, 35, 36, 37},
|
|
71
|
+
shadows = ForegroundServiceTest.DenyOldNotificationShadowService.class)
|
|
72
|
+
public void denyOld_untypedForwardingPreservesFailures() {
|
|
73
|
+
assertForwarding(ForegroundServiceTest.DenyOldNotificationShadowService.class, false);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Test
|
|
77
|
+
@Config(
|
|
78
|
+
sdk = {24, 35, 36, 37},
|
|
79
|
+
shadows = ForegroundServiceTest.RejectBStartForegroundShadowService.class)
|
|
80
|
+
public void rejectB_untypedForwardingPreservesFailures() {
|
|
81
|
+
assertForwarding(ForegroundServiceTest.RejectBStartForegroundShadowService.class, false);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@Test
|
|
85
|
+
@Config(
|
|
86
|
+
sdk = {29, 35, 36, 37},
|
|
87
|
+
shadows = ForegroundServiceTest.RejectBStartForegroundShadowService.class)
|
|
88
|
+
public void rejectB_typedForwardingPreservesFailures() {
|
|
89
|
+
assertForwarding(ForegroundServiceTest.RejectBStartForegroundShadowService.class, true);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private static void resetIssue81() {
|
|
93
|
+
ForegroundServiceTest.Issue81ShadowService.failure = null;
|
|
94
|
+
ForegroundServiceTest.Issue81ShadowService.beforePromotion = null;
|
|
95
|
+
ForegroundServiceTest.Issue81ShadowService.rejectTitle = null;
|
|
96
|
+
ForegroundServiceTest.Issue81ShadowService.promotions.clear();
|
|
97
|
+
ForegroundServiceTest.Issue81ShadowService.types.clear();
|
|
98
|
+
ForegroundServiceTest.Issue81ShadowService.order.clear();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private static Notification notification() {
|
|
102
|
+
Context context = RuntimeEnvironment.getApplication();
|
|
103
|
+
if (Build.VERSION.SDK_INT >= 26) {
|
|
104
|
+
context
|
|
105
|
+
.getSystemService(NotificationManager.class)
|
|
106
|
+
.createNotificationChannel(
|
|
107
|
+
new NotificationChannel("compat", "compat", NotificationManager.IMPORTANCE_LOW));
|
|
108
|
+
return new Notification.Builder(context, "compat").setContentTitle("A").build();
|
|
109
|
+
}
|
|
110
|
+
return new Notification.Builder(context).setContentTitle("A").build();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private static TestService assertForwarding(
|
|
114
|
+
Class<? extends ShadowService> expected, boolean typed) {
|
|
115
|
+
assertEquals(RuntimeEnvironment.getApiLevel(), Build.VERSION.SDK_INT);
|
|
116
|
+
System.out.println(
|
|
117
|
+
"Shadow compatibility: sdk="
|
|
118
|
+
+ RuntimeEnvironment.getApiLevel()
|
|
119
|
+
+ " java="
|
|
120
|
+
+ System.getProperty("java.specification.version"));
|
|
121
|
+
TestService service = Robolectric.buildService(TestService.class).create().get();
|
|
122
|
+
ShadowService shadow = org.robolectric.Shadows.shadowOf(service);
|
|
123
|
+
assertSame(expected, shadow.getClass());
|
|
124
|
+
Notification notification = notification();
|
|
125
|
+
Runnable promote =
|
|
126
|
+
() -> {
|
|
127
|
+
if (typed) {
|
|
128
|
+
service.startForeground(
|
|
129
|
+
100, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
|
130
|
+
} else {
|
|
131
|
+
service.startForeground(100, notification);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
promote.run();
|
|
135
|
+
assertSame(notification, shadow.getLastForegroundNotification());
|
|
136
|
+
assertEquals(100, shadow.getLastForegroundNotificationId());
|
|
137
|
+
assertTrue((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
|
|
138
|
+
if (typed)
|
|
139
|
+
assertEquals(
|
|
140
|
+
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC, service.getForegroundServiceType());
|
|
141
|
+
// Both a platform-style runtime failure and the newly declared checked failure must escape.
|
|
142
|
+
for (Exception failure :
|
|
143
|
+
new Exception[] {new SecurityException("denied"), new Exception("checked")}) {
|
|
144
|
+
Notification rejected = notification();
|
|
145
|
+
shadow.setThrowInStartForeground(failure);
|
|
146
|
+
assertSame(
|
|
147
|
+
failure,
|
|
148
|
+
assertThrows(
|
|
149
|
+
Exception.class,
|
|
150
|
+
() -> {
|
|
151
|
+
if (typed) {
|
|
152
|
+
service.startForeground(
|
|
153
|
+
200, rejected, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
|
154
|
+
} else {
|
|
155
|
+
service.startForeground(200, rejected);
|
|
156
|
+
}
|
|
157
|
+
}));
|
|
158
|
+
assertSame(notification, shadow.getLastForegroundNotification());
|
|
159
|
+
assertEquals(100, shadow.getLastForegroundNotificationId());
|
|
160
|
+
assertEquals(0, rejected.flags & Notification.FLAG_FOREGROUND_SERVICE);
|
|
161
|
+
}
|
|
162
|
+
shadow.setThrowInStartForeground(null);
|
|
163
|
+
promote.run();
|
|
164
|
+
assertSame(notification, shadow.getLastForegroundNotification());
|
|
165
|
+
if (typed)
|
|
166
|
+
assertEquals(
|
|
167
|
+
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC, service.getForegroundServiceType());
|
|
168
|
+
return service;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/cli/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.initNse = initNse;
|
|
40
40
|
const fs = __importStar(require("fs"));
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
|
-
const xcode_1 = __importDefault(require("xcode"));
|
|
42
|
+
const xcode_1 = __importDefault(require("../lib/xcode"));
|
|
43
43
|
const detectProject_1 = require("../lib/detectProject");
|
|
44
44
|
const initNseCore_1 = require("../lib/initNseCore");
|
|
45
45
|
const writeTemplates_1 = require("../lib/writeTemplates");
|
|
@@ -208,4 +208,3 @@ function checkPbxprojTarget(pbxprojPath, targetName) {
|
|
|
208
208
|
}
|
|
209
209
|
return false;
|
|
210
210
|
}
|
|
211
|
-
//# sourceMappingURL=initNse.js.map
|
|
@@ -40,7 +40,7 @@ exports.deriveBundleId = void 0;
|
|
|
40
40
|
exports.detectIosProject = detectIosProject;
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
|
-
const xcode_1 = __importDefault(require("xcode"));
|
|
43
|
+
const xcode_1 = __importDefault(require("./xcode"));
|
|
44
44
|
var initNseCore_1 = require("./initNseCore");
|
|
45
45
|
Object.defineProperty(exports, "deriveBundleId", { enumerable: true, get: function () { return initNseCore_1.deriveNseBundleIdentifier; } });
|
|
46
46
|
/**
|
|
@@ -124,4 +124,3 @@ function readParentTarget(pbxprojPath) {
|
|
|
124
124
|
}
|
|
125
125
|
return { bundleId, targetName };
|
|
126
126
|
}
|
|
127
|
-
//# sourceMappingURL=detectProject.js.map
|
package/cli/dist/lib/logger.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Xcode project patching via xcode@3.
|
|
3
|
+
* Xcode project patching via the stable vendored xcode@3.0.1 compatibility layer.
|
|
4
4
|
*
|
|
5
5
|
* xcode@3.x has three known bugs that this module works around. See inline
|
|
6
6
|
* comments tagged "xcode@3.x bug" for details. Do NOT remove these
|
|
@@ -53,7 +53,7 @@ exports.patchXcodeProject = patchXcodeProject;
|
|
|
53
53
|
exports.patchXcodeProjectForNotifyKitNse = patchXcodeProjectForNotifyKitNse;
|
|
54
54
|
const crypto = __importStar(require("crypto"));
|
|
55
55
|
const fs = __importStar(require("fs"));
|
|
56
|
-
const xcode_1 = __importDefault(require("xcode"));
|
|
56
|
+
const xcode_1 = __importDefault(require("./xcode"));
|
|
57
57
|
/**
|
|
58
58
|
* Adds an NSE target to the .pbxproj file via the xcode library.
|
|
59
59
|
* Idempotent: if a target with the given name already exists, returns false.
|
|
@@ -102,6 +102,10 @@ function patchXcodeProjectForNotifyKitNse(proj, options) {
|
|
|
102
102
|
proj.addSourceFile(`${targetName}/NotificationService.swift`, {
|
|
103
103
|
target: targetUuid,
|
|
104
104
|
}, group.uuid);
|
|
105
|
+
// The stable writer serializes undefined JS values as the bare word
|
|
106
|
+
// "undefined". addSourceFile also creates an unset explicitFileType;
|
|
107
|
+
// omit it on our new reference, preserving every existing reference.
|
|
108
|
+
fixSourceFileReference(proj, `${targetName}/NotificationService.swift`);
|
|
105
109
|
// xcode@3.x bug: addTargetDependency() adds the dependency to an internal
|
|
106
110
|
// cache but does not serialize it to the project hash, so writeSync()
|
|
107
111
|
// emits a pbxproj with no dependency entry. CocoaPods' host-target
|
|
@@ -199,6 +203,22 @@ function fixProductFileReference(proj, targetName) {
|
|
|
199
203
|
}
|
|
200
204
|
}
|
|
201
205
|
}
|
|
206
|
+
function fixSourceFileReference(proj, sourcePath) {
|
|
207
|
+
const fileRefs = proj.hash.project.objects.PBXFileReference;
|
|
208
|
+
if (!fileRefs)
|
|
209
|
+
return;
|
|
210
|
+
for (const value of Object.values(fileRefs)) {
|
|
211
|
+
if (!value || typeof value !== 'object')
|
|
212
|
+
continue;
|
|
213
|
+
const ref = value;
|
|
214
|
+
if (String(ref.path ?? '').replace(/^"|"$/g, '') !== sourcePath)
|
|
215
|
+
continue;
|
|
216
|
+
for (const key of Object.keys(ref)) {
|
|
217
|
+
if (ref[key] === undefined)
|
|
218
|
+
delete ref[key];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
202
222
|
function genUuid() {
|
|
203
223
|
return crypto.randomBytes(12).toString('hex').toUpperCase().slice(0, 24);
|
|
204
224
|
}
|
|
@@ -264,4 +284,3 @@ function stripRnfbInfoPlistInputPath(proj, hostUuid) {
|
|
|
264
284
|
}
|
|
265
285
|
}
|
|
266
286
|
}
|
|
267
|
-
//# sourceMappingURL=patchXcodeProject.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Keeping this relative path works in both src/lib and the compiled dist/lib.
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
5
|
+
const xcode = require('../../vendor/xcode');
|
|
6
|
+
exports.default = xcode;
|
|
@@ -1,32 +1,100 @@
|
|
|
1
|
+
import Foundation
|
|
1
2
|
import UserNotifications
|
|
2
3
|
import RNNotifeeCore
|
|
3
4
|
|
|
5
|
+
private func nseLog(_ message: String) {
|
|
6
|
+
NSLog("[NotifyKitNSE] %@", message)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
private func requestedAttachmentURLs(from userInfo: [AnyHashable: Any]) -> [String] {
|
|
10
|
+
guard let serializedOptions = userInfo["notifee_options"] as? String,
|
|
11
|
+
let data = serializedOptions.data(using: .utf8),
|
|
12
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
13
|
+
let ios = json["ios"] as? [String: Any],
|
|
14
|
+
let attachments = ios["attachments"] as? [[String: Any]] else {
|
|
15
|
+
return []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return attachments.compactMap { attachment in
|
|
19
|
+
attachment["url"] as? String
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
4
23
|
class NotificationService: UNNotificationServiceExtension {
|
|
5
24
|
var contentHandler: ((UNNotificationContent) -> Void)?
|
|
6
25
|
var bestAttemptContent: UNMutableNotificationContent?
|
|
26
|
+
private let deliveryLock = NSLock()
|
|
27
|
+
private var didDeliver = false
|
|
7
28
|
|
|
8
29
|
override func didReceive(
|
|
9
30
|
_ request: UNNotificationRequest,
|
|
10
31
|
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
|
11
32
|
) {
|
|
33
|
+
let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent
|
|
34
|
+
|
|
35
|
+
deliveryLock.lock()
|
|
36
|
+
didDeliver = false
|
|
12
37
|
self.contentHandler = contentHandler
|
|
13
|
-
self.bestAttemptContent =
|
|
38
|
+
self.bestAttemptContent = mutableContent
|
|
39
|
+
deliveryLock.unlock()
|
|
40
|
+
|
|
41
|
+
let requestedAttachmentUrls = requestedAttachmentURLs(from: request.content.userInfo)
|
|
14
42
|
|
|
15
|
-
|
|
16
|
-
|
|
43
|
+
nseLog(
|
|
44
|
+
"didReceive id=\(request.identifier) title=\(request.content.title) " +
|
|
45
|
+
"hasNotifeeOptions=\(request.content.userInfo["notifee_options"] != nil) " +
|
|
46
|
+
"requestedAttachments=\(requestedAttachmentUrls.count) " +
|
|
47
|
+
"urls=\(requestedAttachmentUrls.joined(separator: ","))"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
guard let bestAttemptContent = mutableContent else {
|
|
51
|
+
nseLog("mutableCopy failed for id=\(request.identifier); delivering original content")
|
|
52
|
+
deliverOnce(request.content)
|
|
17
53
|
return
|
|
18
54
|
}
|
|
19
55
|
|
|
20
56
|
NotifeeExtensionHelper.populateNotificationContent(
|
|
21
57
|
request,
|
|
22
58
|
with: bestAttemptContent,
|
|
23
|
-
withContentHandler:
|
|
59
|
+
withContentHandler: { [weak self] content in
|
|
60
|
+
let deliveredAttachmentIds = content.attachments.map(\.identifier).joined(separator: ",")
|
|
61
|
+
nseLog(
|
|
62
|
+
"contentHandler id=\(request.identifier) title=\(content.title) " +
|
|
63
|
+
"deliveredAttachments=\(content.attachments.count) " +
|
|
64
|
+
"identifiers=\(deliveredAttachmentIds)"
|
|
65
|
+
)
|
|
66
|
+
self?.deliverOnce(content)
|
|
67
|
+
}
|
|
24
68
|
)
|
|
25
69
|
}
|
|
26
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
|
+
|
|
27
86
|
override func serviceExtensionTimeWillExpire() {
|
|
28
|
-
|
|
29
|
-
|
|
87
|
+
deliveryLock.lock()
|
|
88
|
+
let content = bestAttemptContent
|
|
89
|
+
deliveryLock.unlock()
|
|
90
|
+
|
|
91
|
+
if let bestAttemptContent = content {
|
|
92
|
+
nseLog(
|
|
93
|
+
"serviceExtensionTimeWillExpire id=\(bestAttemptContent.userInfo["gcm.message_id"] ?? "n/a") " +
|
|
94
|
+
"title=\(bestAttemptContent.title) " +
|
|
95
|
+
"deliveredAttachments=\(bestAttemptContent.attachments.count)"
|
|
96
|
+
)
|
|
97
|
+
deliverOnce(bestAttemptContent)
|
|
30
98
|
}
|
|
31
99
|
}
|
|
32
100
|
}
|
package/cli/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"10.9.0"}
|