react-native-notify-kit 10.1.0 → 10.2.1
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 +99 -96
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
- package/android/src/main/java/app/notifee/core/NotificationManager.java +21 -8
- package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
- package/android/src/main/java/app/notifee/core/ReceiverService.java +18 -13
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidActionModel.java +1 -2
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidPressActionModel.java +3 -9
- package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
- package/android/src/main/java/app/notifee/core/utility/IntentUtils.java +0 -28
- package/android/src/main/java/app/notifee/core/utility/PowerManagerUtils.java +79 -41
- package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +5 -1
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeReactUtils.kt +1 -2
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +150 -0
- package/cli/dist/lib/patchPodfile.d.ts +3 -1
- package/cli/dist/lib/patchPodfile.js +125 -33
- package/cli/dist/lib/patchPodfile.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/types/Module.d.ts +27 -13
- package/dist/types/Notification.d.ts +1 -1
- package/dist/types/NotificationIOS.d.ts +44 -21
- package/dist/types/NotificationIOS.js +15 -1
- package/dist/types/NotificationIOS.js.map +1 -1
- package/dist/types/PowerManagerInfo.d.ts +9 -4
- package/dist/types/Trigger.d.ts +45 -2
- package/dist/types/Trigger.js +22 -0
- package/dist/types/Trigger.js.map +1 -1
- package/dist/validators/validateIOSCategory.js +2 -2
- package/dist/validators/validateIOSCategory.js.map +1 -1
- package/dist/validators/validateTrigger.js +26 -1
- package/dist/validators/validateTrigger.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +20 -10
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +1 -2
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +44 -35
- package/ios/NotifeeCore/NotifeeCore.m +1042 -119
- package/ios/NotifeeCore/NotifeeCoreUtil.h +36 -1
- package/ios/NotifeeCore/NotifeeCoreUtil.m +533 -9
- package/ios/RNNotifee/NotifeeApiModule.mm +2 -2
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/types/Module.ts +27 -13
- package/src/types/Notification.ts +1 -1
- package/src/types/NotificationIOS.ts +43 -28
- package/src/types/PowerManagerInfo.ts +9 -4
- package/src/types/Trigger.ts +45 -1
- package/src/validators/validateIOSCategory.ts +4 -2
- package/src/validators/validateTrigger.ts +38 -0
- package/src/version.ts +1 -1
|
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
|
|
|
7
7
|
import android.os.Bundle;
|
|
8
8
|
import java.util.Calendar;
|
|
9
9
|
import java.util.TimeZone;
|
|
10
|
+
import java.util.concurrent.TimeUnit;
|
|
10
11
|
import org.junit.After;
|
|
11
12
|
import org.junit.Assume;
|
|
12
13
|
import org.junit.Before;
|
|
@@ -23,6 +24,7 @@ public class TimestampTriggerModelTest {
|
|
|
23
24
|
private static final int REPEAT_FREQUENCY_HOURLY = 0;
|
|
24
25
|
private static final int REPEAT_FREQUENCY_DAILY = 1;
|
|
25
26
|
private static final int REPEAT_FREQUENCY_WEEKLY = 2;
|
|
27
|
+
private static final int REPEAT_FREQUENCY_MONTHLY = 3;
|
|
26
28
|
|
|
27
29
|
private TimestampTriggerModel mTimestampTriggerModel = null;
|
|
28
30
|
private TimeZone mOriginalTimeZone;
|
|
@@ -77,6 +79,42 @@ public class TimestampTriggerModelTest {
|
|
|
77
79
|
return TimestampTriggerModel.fromBundle(trigger);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
private TimestampTriggerModel buildRepeatingTrigger(
|
|
83
|
+
long timestamp, int repeatFrequency, int repeatInterval) {
|
|
84
|
+
Bundle trigger = new Bundle();
|
|
85
|
+
trigger.putLong("timestamp", timestamp);
|
|
86
|
+
trigger.putInt("repeatFrequency", repeatFrequency);
|
|
87
|
+
trigger.putInt("repeatInterval", repeatInterval);
|
|
88
|
+
return TimestampTriggerModel.fromBundle(trigger);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private long expectedNextTimestamp(long timestamp, int field, int repeatInterval) {
|
|
92
|
+
Calendar cal = Calendar.getInstance();
|
|
93
|
+
cal.setTimeInMillis(timestamp);
|
|
94
|
+
while (cal.getTimeInMillis() < System.currentTimeMillis()) {
|
|
95
|
+
cal.add(field, repeatInterval);
|
|
96
|
+
}
|
|
97
|
+
return cal.getTimeInMillis();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Test
|
|
101
|
+
public void repeatingTrigger_withoutRepeatInterval_defaultsToOne() {
|
|
102
|
+
TimestampTriggerModel trigger =
|
|
103
|
+
buildRepeatingTrigger(mNow + ONE_DAY_MS, REPEAT_FREQUENCY_DAILY);
|
|
104
|
+
|
|
105
|
+
assertEquals("daily repeat interval should default to 1 day", 1, trigger.getInterval());
|
|
106
|
+
assertEquals("daily repeat time unit should be days", TimeUnit.DAYS, trigger.getTimeUnit());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Test
|
|
110
|
+
public void repeatingTrigger_invalidNativeRepeatInterval_fallsBackToOne() {
|
|
111
|
+
TimestampTriggerModel trigger =
|
|
112
|
+
buildRepeatingTrigger(mNow + ONE_DAY_MS, REPEAT_FREQUENCY_DAILY, 0);
|
|
113
|
+
|
|
114
|
+
assertEquals("invalid native repeatInterval should fall back to 1", 1, trigger.getInterval());
|
|
115
|
+
assertEquals(TimeUnit.DAYS, trigger.getTimeUnit());
|
|
116
|
+
}
|
|
117
|
+
|
|
80
118
|
@Test
|
|
81
119
|
public void setNextTimestamp_daily_advancesToTomorrowSameWallClock() {
|
|
82
120
|
long original = mNow - ONE_MINUTE_MS;
|
|
@@ -101,6 +139,22 @@ public class TimestampTriggerModelTest {
|
|
|
101
139
|
assertEquals("wall-clock second preserved", originalSecond, nextCal.get(Calendar.SECOND));
|
|
102
140
|
}
|
|
103
141
|
|
|
142
|
+
@Test
|
|
143
|
+
public void setNextTimestamp_dailyEveryTwoDays_advancesByRepeatInterval() {
|
|
144
|
+
long original = mNow - ONE_MINUTE_MS;
|
|
145
|
+
TimestampTriggerModel trigger = buildRepeatingTrigger(original, REPEAT_FREQUENCY_DAILY, 2);
|
|
146
|
+
|
|
147
|
+
trigger.setNextTimestamp();
|
|
148
|
+
long next = trigger.getTimestamp();
|
|
149
|
+
|
|
150
|
+
assertEquals(
|
|
151
|
+
"daily repeatInterval=2 should use Calendar.add(DAY_OF_MONTH, 2)",
|
|
152
|
+
expectedNextTimestamp(original, Calendar.DAY_OF_MONTH, 2),
|
|
153
|
+
next);
|
|
154
|
+
assertEquals("WorkManager interval should be 2 days", 2, trigger.getInterval());
|
|
155
|
+
assertEquals("WorkManager time unit should be days", TimeUnit.DAYS, trigger.getTimeUnit());
|
|
156
|
+
}
|
|
157
|
+
|
|
104
158
|
@Test
|
|
105
159
|
public void setNextTimestamp_daily_multipleMissedFires_skipsToFuture() {
|
|
106
160
|
// Offset by 1 minute so the original does not land exactly on a multiple of 24h from mNow.
|
|
@@ -116,6 +170,22 @@ public class TimestampTriggerModelTest {
|
|
|
116
170
|
assertTrue("next timestamp must not be more than 25h ahead", next < mNow + 25L * ONE_HOUR_MS);
|
|
117
171
|
}
|
|
118
172
|
|
|
173
|
+
@Test
|
|
174
|
+
public void setNextTimestamp_weeklyEveryTwoWeeks_advancesByRepeatInterval() {
|
|
175
|
+
long original = mNow - ONE_MINUTE_MS;
|
|
176
|
+
TimestampTriggerModel trigger = buildRepeatingTrigger(original, REPEAT_FREQUENCY_WEEKLY, 2);
|
|
177
|
+
|
|
178
|
+
trigger.setNextTimestamp();
|
|
179
|
+
long next = trigger.getTimestamp();
|
|
180
|
+
|
|
181
|
+
assertEquals(
|
|
182
|
+
"weekly repeatInterval=2 should use Calendar.add(WEEK_OF_YEAR, 2)",
|
|
183
|
+
expectedNextTimestamp(original, Calendar.WEEK_OF_YEAR, 2),
|
|
184
|
+
next);
|
|
185
|
+
assertEquals("WorkManager interval should be 14 days", 14, trigger.getInterval());
|
|
186
|
+
assertEquals("WorkManager time unit should be days", TimeUnit.DAYS, trigger.getTimeUnit());
|
|
187
|
+
}
|
|
188
|
+
|
|
119
189
|
@Test
|
|
120
190
|
public void setNextTimestamp_weekly_advancesOneWeek() {
|
|
121
191
|
long original = mNow - ONE_MINUTE_MS;
|
|
@@ -130,6 +200,48 @@ public class TimestampTriggerModelTest {
|
|
|
130
200
|
assertTrue("weekly next timestamp must be <= now + 7d1h", next <= upper);
|
|
131
201
|
}
|
|
132
202
|
|
|
203
|
+
@Test
|
|
204
|
+
public void setNextTimestamp_monthlyEveryThreeMonths_advancesByRepeatInterval() {
|
|
205
|
+
long original = mNow - ONE_MINUTE_MS;
|
|
206
|
+
TimestampTriggerModel trigger = buildRepeatingTrigger(original, REPEAT_FREQUENCY_MONTHLY, 3);
|
|
207
|
+
|
|
208
|
+
trigger.setNextTimestamp();
|
|
209
|
+
long next = trigger.getTimestamp();
|
|
210
|
+
|
|
211
|
+
assertEquals(
|
|
212
|
+
"monthly repeatInterval=3 should use Calendar.add(MONTH, 3)",
|
|
213
|
+
expectedNextTimestamp(original, Calendar.MONTH, 3),
|
|
214
|
+
next);
|
|
215
|
+
assertEquals(TimestampTriggerModel.MONTHLY, trigger.getRepeatFrequency());
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@Test
|
|
219
|
+
public void setNextTimestamp_monthlyEndOfMonth_usesCalendarClampSemantics() {
|
|
220
|
+
TimeZone utc = TimeZone.getTimeZone("UTC");
|
|
221
|
+
TimeZone.setDefault(utc);
|
|
222
|
+
|
|
223
|
+
Calendar start = Calendar.getInstance(utc);
|
|
224
|
+
start.clear();
|
|
225
|
+
start.set(2020, Calendar.JANUARY, 31, 12, 45, 0);
|
|
226
|
+
long original = start.getTimeInMillis();
|
|
227
|
+
|
|
228
|
+
TimestampTriggerModel trigger = buildRepeatingTrigger(original, REPEAT_FREQUENCY_MONTHLY, 1);
|
|
229
|
+
|
|
230
|
+
trigger.setNextTimestamp();
|
|
231
|
+
long next = trigger.getTimestamp();
|
|
232
|
+
|
|
233
|
+
assertEquals(
|
|
234
|
+
"monthly end-of-month should match native Calendar.add clamp behavior",
|
|
235
|
+
expectedNextTimestamp(original, Calendar.MONTH, 1),
|
|
236
|
+
next);
|
|
237
|
+
|
|
238
|
+
Calendar nextCal = Calendar.getInstance(utc);
|
|
239
|
+
nextCal.setTimeInMillis(next);
|
|
240
|
+
assertTrue(
|
|
241
|
+
"Calendar.add should clamp the Jan 31 anchor before future monthly repeats",
|
|
242
|
+
nextCal.get(Calendar.DAY_OF_MONTH) < 31);
|
|
243
|
+
}
|
|
244
|
+
|
|
133
245
|
@Test
|
|
134
246
|
public void setNextTimestamp_hourly_advancesOneHour() {
|
|
135
247
|
long original = mNow - ONE_MINUTE_MS;
|
|
@@ -144,6 +256,44 @@ public class TimestampTriggerModelTest {
|
|
|
144
256
|
assertTrue("hourly next timestamp must be <= now + 61m", next <= upper);
|
|
145
257
|
}
|
|
146
258
|
|
|
259
|
+
@Test
|
|
260
|
+
public void setNextTimestamp_dailyEveryTwoDaysAcrossDstSpringForward() {
|
|
261
|
+
TimeZone rome = TimeZone.getTimeZone("Europe/Rome");
|
|
262
|
+
TimeZone.setDefault(rome);
|
|
263
|
+
|
|
264
|
+
Calendar start = Calendar.getInstance(rome);
|
|
265
|
+
start.clear();
|
|
266
|
+
start.set(2026, Calendar.MARCH, 28, 4, 30, 0);
|
|
267
|
+
long originalTimestamp = start.getTimeInMillis();
|
|
268
|
+
|
|
269
|
+
Calendar windowStart = Calendar.getInstance(rome);
|
|
270
|
+
windowStart.clear();
|
|
271
|
+
windowStart.set(2026, Calendar.MARCH, 31, 0, 0, 0);
|
|
272
|
+
Calendar windowEnd = Calendar.getInstance(rome);
|
|
273
|
+
windowEnd.clear();
|
|
274
|
+
windowEnd.set(2026, Calendar.OCTOBER, 24, 23, 59, 59);
|
|
275
|
+
long now = System.currentTimeMillis();
|
|
276
|
+
Assume.assumeTrue(
|
|
277
|
+
"spring-forward repeatInterval discrimination requires current time in"
|
|
278
|
+
+ " [2026-03-31, 2026-10-24] Europe/Rome",
|
|
279
|
+
now >= windowStart.getTimeInMillis() && now <= windowEnd.getTimeInMillis());
|
|
280
|
+
|
|
281
|
+
TimestampTriggerModel trigger =
|
|
282
|
+
buildRepeatingTrigger(originalTimestamp, REPEAT_FREQUENCY_DAILY, 2);
|
|
283
|
+
trigger.setNextTimestamp();
|
|
284
|
+
long next = trigger.getTimestamp();
|
|
285
|
+
|
|
286
|
+
Calendar nextCal = Calendar.getInstance(rome);
|
|
287
|
+
nextCal.setTimeInMillis(next);
|
|
288
|
+
assertTrue("next timestamp must be >= now", next >= now);
|
|
289
|
+
assertEquals(
|
|
290
|
+
"wall-clock hour must remain 4 with repeatInterval=2",
|
|
291
|
+
4,
|
|
292
|
+
nextCal.get(Calendar.HOUR_OF_DAY));
|
|
293
|
+
assertEquals("wall-clock minute must remain 30", 30, nextCal.get(Calendar.MINUTE));
|
|
294
|
+
assertEquals("wall-clock second must remain 0", 0, nextCal.get(Calendar.SECOND));
|
|
295
|
+
}
|
|
296
|
+
|
|
147
297
|
@Test
|
|
148
298
|
public void setNextTimestamp_dailyAcrossDstSpringForward() {
|
|
149
299
|
// Europe/Rome spring-forward 2026: 2026-03-29 02:00 local jumps to 03:00 local. The 29
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Patches the Podfile to add the NSE target with RNNotifeeCore pod.
|
|
3
3
|
* The NSE target is nested inside the main app target so CocoaPods can
|
|
4
4
|
* detect the host→extension relationship. Uses `inherit! :search_paths`.
|
|
5
|
-
*
|
|
5
|
+
* Also installs a post_install hook that keeps React Native Firebase's
|
|
6
|
+
* generated Info.plist input path from recreating a host-extension build cycle.
|
|
7
|
+
* Idempotent: returns false when no Podfile changes are needed.
|
|
6
8
|
*/
|
|
7
9
|
export declare function patchPodfile(podfilePath: string, targetName: string, dryRun: boolean): boolean;
|
|
8
10
|
/**
|
|
@@ -36,21 +36,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.patchPodfile = patchPodfile;
|
|
37
37
|
exports.getPatchedPodfile = getPatchedPodfile;
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
+
const RNFB_INFO_PLIST_INPUT_PATH = '$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)';
|
|
40
|
+
const RNFB_POST_INSTALL_MARKER = 'NotifyKitNSE: avoid an Xcode build cycle between the embedded app extension';
|
|
39
41
|
/**
|
|
40
42
|
* Patches the Podfile to add the NSE target with RNNotifeeCore pod.
|
|
41
43
|
* The NSE target is nested inside the main app target so CocoaPods can
|
|
42
44
|
* detect the host→extension relationship. Uses `inherit! :search_paths`.
|
|
43
|
-
*
|
|
45
|
+
* Also installs a post_install hook that keeps React Native Firebase's
|
|
46
|
+
* generated Info.plist input path from recreating a host-extension build cycle.
|
|
47
|
+
* Idempotent: returns false when no Podfile changes are needed.
|
|
44
48
|
*/
|
|
45
49
|
function patchPodfile(podfilePath, targetName, dryRun) {
|
|
46
50
|
const content = fs.readFileSync(podfilePath, 'utf-8');
|
|
47
|
-
|
|
48
|
-
if (hasUncommentedTarget(content, targetName)) {
|
|
49
|
-
return false; // Already present
|
|
50
|
-
}
|
|
51
|
-
const patched = insertNseTarget(content, targetName);
|
|
51
|
+
const patched = getPatchedPodfile(content, targetName);
|
|
52
52
|
if (patched === null) {
|
|
53
|
-
return false; //
|
|
53
|
+
return false; // Already patched
|
|
54
54
|
}
|
|
55
55
|
if (!dryRun) {
|
|
56
56
|
fs.writeFileSync(podfilePath, patched, 'utf-8');
|
|
@@ -62,10 +62,23 @@ function patchPodfile(podfilePath, targetName, dryRun) {
|
|
|
62
62
|
* preview or testing).
|
|
63
63
|
*/
|
|
64
64
|
function getPatchedPodfile(content, targetName) {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
let patched = content;
|
|
66
|
+
let changed = false;
|
|
67
|
+
// Idempotency check — skip commented lines (# prefix)
|
|
68
|
+
if (!hasUncommentedTarget(patched, targetName)) {
|
|
69
|
+
const withNseTarget = insertNseTarget(patched, targetName);
|
|
70
|
+
if (withNseTarget === null) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
patched = withNseTarget;
|
|
74
|
+
changed = true;
|
|
67
75
|
}
|
|
68
|
-
|
|
76
|
+
const withRnfbPatch = ensureRnfbPostInstallPatch(patched);
|
|
77
|
+
if (withRnfbPatch !== patched) {
|
|
78
|
+
patched = withRnfbPatch;
|
|
79
|
+
changed = true;
|
|
80
|
+
}
|
|
81
|
+
return changed ? patched : null;
|
|
69
82
|
}
|
|
70
83
|
/**
|
|
71
84
|
* Inserts the NSE target block inside the main app target, just before
|
|
@@ -93,39 +106,118 @@ function insertNseTarget(content, targetName) {
|
|
|
93
106
|
// No target found — append at top level (unusual Podfile)
|
|
94
107
|
return content + '\n' + block;
|
|
95
108
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
const insertIndex = findMatchingRubyBlockEnd(content, targetMatch.index);
|
|
110
|
+
if (insertIndex === -1) {
|
|
111
|
+
// Could not find matching end — abort rather than silently producing invalid output
|
|
112
|
+
throw new Error("Could not locate main app target's closing 'end' in Podfile. NSE insertion aborted. " +
|
|
113
|
+
'Your Podfile may use abstract_target, unusual formatting, or nested blocks — ' +
|
|
114
|
+
'add the NSE target manually per the legacy guide.');
|
|
115
|
+
}
|
|
116
|
+
return content.slice(0, insertIndex) + block + content.slice(insertIndex);
|
|
117
|
+
}
|
|
118
|
+
function ensureRnfbPostInstallPatch(content) {
|
|
119
|
+
if (content.includes(RNFB_POST_INSTALL_MARKER)) {
|
|
120
|
+
return content;
|
|
121
|
+
}
|
|
122
|
+
const postInstall = findPostInstallBlock(content);
|
|
123
|
+
if (postInstall) {
|
|
124
|
+
const snippet = '\n' + buildRnfbPostInstallSnippet(postInstall.bodyIndent, postInstall.paramName);
|
|
125
|
+
return content.slice(0, postInstall.endIndex) + snippet + content.slice(postInstall.endIndex);
|
|
126
|
+
}
|
|
127
|
+
const separator = content.trim().length === 0 || content.endsWith('\n') ? '\n' : '\n\n';
|
|
128
|
+
return (content +
|
|
129
|
+
separator +
|
|
130
|
+
'post_install do |installer|\n' +
|
|
131
|
+
buildRnfbPostInstallSnippet(' ', 'installer') +
|
|
132
|
+
'end\n');
|
|
133
|
+
}
|
|
134
|
+
function buildRnfbPostInstallSnippet(indent, installerParamName) {
|
|
135
|
+
return [
|
|
136
|
+
`${indent}# ${RNFB_POST_INSTALL_MARKER}`,
|
|
137
|
+
`${indent}# and React Native Firebase's Info.plist processing phase.`,
|
|
138
|
+
`${indent}rnfb_info_plist_input_path = '${RNFB_INFO_PLIST_INPUT_PATH}'`,
|
|
139
|
+
`${indent}rnfb_phase_names = [`,
|
|
140
|
+
`${indent} '[RNFB] Core Configuration',`,
|
|
141
|
+
`${indent} '[CP-User] [RNFB] Core Configuration',`,
|
|
142
|
+
`${indent}]`,
|
|
143
|
+
'',
|
|
144
|
+
`${indent}${installerParamName}.aggregate_targets.each do |aggregate_target|`,
|
|
145
|
+
`${indent} aggregate_target.target_definition.script_phases.each do |script_phase|`,
|
|
146
|
+
`${indent} next unless rnfb_phase_names.include?(script_phase[:name])`,
|
|
147
|
+
`${indent} next unless script_phase[:input_files]`,
|
|
148
|
+
'',
|
|
149
|
+
`${indent} script_phase[:input_files].delete(rnfb_info_plist_input_path)`,
|
|
150
|
+
`${indent} end`,
|
|
151
|
+
'',
|
|
152
|
+
`${indent} user_project = aggregate_target.user_project`,
|
|
153
|
+
`${indent} next unless user_project`,
|
|
154
|
+
'',
|
|
155
|
+
`${indent} rnfb_input_path_removed = false`,
|
|
156
|
+
'',
|
|
157
|
+
`${indent} user_project.targets.each do |target|`,
|
|
158
|
+
`${indent} target.shell_script_build_phases.each do |phase|`,
|
|
159
|
+
`${indent} next unless rnfb_phase_names.include?(phase.name)`,
|
|
160
|
+
`${indent} next unless phase.input_paths`,
|
|
161
|
+
'',
|
|
162
|
+
`${indent} if phase.input_paths.delete(rnfb_info_plist_input_path)`,
|
|
163
|
+
`${indent} rnfb_input_path_removed = true`,
|
|
164
|
+
`${indent} end`,
|
|
165
|
+
`${indent} end`,
|
|
166
|
+
`${indent} end`,
|
|
167
|
+
'',
|
|
168
|
+
`${indent} user_project.save if rnfb_input_path_removed`,
|
|
169
|
+
`${indent}end`,
|
|
170
|
+
'',
|
|
171
|
+
].join('\n');
|
|
172
|
+
}
|
|
173
|
+
function findPostInstallBlock(content) {
|
|
174
|
+
const postInstallPattern = /^([ \t]*)post_install\s+do\s+\|([^|]+)\|\s*(?:#.*)?$/gm;
|
|
175
|
+
let match;
|
|
176
|
+
while ((match = postInstallPattern.exec(content)) !== null) {
|
|
177
|
+
const endIndex = findMatchingRubyBlockEnd(content, match.index);
|
|
178
|
+
if (endIndex !== -1) {
|
|
179
|
+
return {
|
|
180
|
+
bodyIndent: `${match[1]} `,
|
|
181
|
+
endIndex,
|
|
182
|
+
paramName: match[2].trim(),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function findMatchingRubyBlockEnd(content, startIndex) {
|
|
189
|
+
const afterStart = content.slice(startIndex);
|
|
190
|
+
const lines = afterStart.split('\n');
|
|
101
191
|
let depth = 0;
|
|
102
|
-
let
|
|
103
|
-
const lines = afterTarget.split('\n');
|
|
104
|
-
let charIndex = targetMatch.index;
|
|
192
|
+
let charIndex = startIndex;
|
|
105
193
|
for (const line of lines) {
|
|
106
|
-
const trimmed = line.trim();
|
|
107
|
-
|
|
108
|
-
if (/\bdo\b(\s*\|[^|]*\|)?\s*$/.test(trimmed) && !trimmed.startsWith('#')) {
|
|
109
|
-
depth++;
|
|
110
|
-
}
|
|
111
|
-
// Count block closers
|
|
194
|
+
const trimmed = stripRubyLineComment(line).trim();
|
|
195
|
+
depth += countRubyBlockOpeners(trimmed);
|
|
112
196
|
if (trimmed === 'end') {
|
|
113
197
|
depth--;
|
|
114
198
|
if (depth === 0) {
|
|
115
|
-
|
|
116
|
-
insertIndex = charIndex;
|
|
117
|
-
break;
|
|
199
|
+
return charIndex;
|
|
118
200
|
}
|
|
119
201
|
}
|
|
120
202
|
charIndex += line.length + 1; // +1 for newline
|
|
121
203
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
204
|
+
return -1;
|
|
205
|
+
}
|
|
206
|
+
function countRubyBlockOpeners(line) {
|
|
207
|
+
if (line.length === 0) {
|
|
208
|
+
return 0;
|
|
127
209
|
}
|
|
128
|
-
|
|
210
|
+
const startsWithKeywordBlock = /^(if|unless|case|begin|while|until|for|def|class|module)\b/.test(line);
|
|
211
|
+
if (startsWithKeywordBlock) {
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
if (/\bdo\b(\s*\|[^|]*\|)?\s*$/.test(line)) {
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
function stripRubyLineComment(line) {
|
|
220
|
+
return line.replace(/#.*$/, '');
|
|
129
221
|
}
|
|
130
222
|
function hasUncommentedTarget(content, targetName) {
|
|
131
223
|
const pattern = new RegExp(`target\\s+['"]${escapeRegex(targetName)}['"]`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patchPodfile.js","sourceRoot":"","sources":["../../src/lib/patchPodfile.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"patchPodfile.js","sourceRoot":"","sources":["../../src/lib/patchPodfile.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,3 +8,5 @@ export * from './types/NotificationIOS';
|
|
|
8
8
|
export * from './types/NotificationAndroid';
|
|
9
9
|
export * from './types/PowerManagerInfo';
|
|
10
10
|
export type { FcmRemoteMessage, FcmConfig } from './fcm/types';
|
|
11
|
+
export type { ModuleWithStatics } from './types/Module';
|
|
12
|
+
export type { WebNotificationSettings } from './types/NotificationWeb';
|
package/dist/types/Module.d.ts
CHANGED
|
@@ -490,20 +490,20 @@ export interface Module {
|
|
|
490
490
|
/**
|
|
491
491
|
* API used to configure iOS notification handling behavior.
|
|
492
492
|
*
|
|
493
|
-
* Use this to control whether
|
|
493
|
+
* Use this to control whether Notify Kit should handle remote (push) notifications
|
|
494
494
|
* on iOS. When `handleRemoteNotifications` is set to `false`, remote notifications
|
|
495
495
|
* (e.g. from Firebase Cloud Messaging) will be forwarded to the original
|
|
496
|
-
* notification delegate instead of being processed by
|
|
496
|
+
* notification delegate instead of being processed by Notify Kit.
|
|
497
497
|
*
|
|
498
498
|
* This allows libraries like React Native Firebase Messaging to receive tap events
|
|
499
499
|
* via `onNotificationOpenedApp()` and `getInitialNotification()`.
|
|
500
500
|
*
|
|
501
|
-
* Defaults to `true` (
|
|
501
|
+
* Defaults to `true` (Notify Kit handles all notifications) for backward compatibility.
|
|
502
502
|
*
|
|
503
503
|
* ```js
|
|
504
504
|
* import notifee from 'react-native-notify-kit';
|
|
505
505
|
*
|
|
506
|
-
* // Disable
|
|
506
|
+
* // Disable Notify Kit handling of remote notifications
|
|
507
507
|
* await notifee.setNotificationConfig({
|
|
508
508
|
* ios: { handleRemoteNotifications: false },
|
|
509
509
|
* });
|
|
@@ -536,9 +536,17 @@ export interface Module {
|
|
|
536
536
|
*/
|
|
537
537
|
isBatteryOptimizationEnabled(): Promise<boolean>;
|
|
538
538
|
/**
|
|
539
|
-
* API used to get information about the device and its power manager settings, including manufacturer, model, version and activity.
|
|
539
|
+
* API used to get best-effort information about the device and its power manager settings, including manufacturer, model, version and a known activity candidate.
|
|
540
540
|
*
|
|
541
|
-
*
|
|
541
|
+
* The returned `activity` is based on Notify Kit's manufacturer mapping and is not
|
|
542
|
+
* prevalidated with `PackageManager`. A non-null value does not guarantee that
|
|
543
|
+
* `openPowerManagerSettings()` can open that screen on the current device firmware.
|
|
544
|
+
*
|
|
545
|
+
* Notify Kit does not rely on Android 11+ package-visibility queries for this helper,
|
|
546
|
+
* so consumer apps do not need to add `<queries>` to use it.
|
|
547
|
+
*
|
|
548
|
+
* If `activity` is `null`, `openPowerManagerSettings()` will be a no-op because
|
|
549
|
+
* there is no known vendor-settings candidate.
|
|
542
550
|
*
|
|
543
551
|
* On iOS, an instance of `PowerManagerInfo` will be returned with `activity` set to `null`.
|
|
544
552
|
*
|
|
@@ -553,7 +561,7 @@ export interface Module {
|
|
|
553
561
|
* // 1. ask the user to adjust their Power Manager settings
|
|
554
562
|
* // ...
|
|
555
563
|
*
|
|
556
|
-
* // 2. open settings
|
|
564
|
+
* // 2. open settings best-effort
|
|
557
565
|
* await notifee.openPowerManagerSettings();
|
|
558
566
|
* }
|
|
559
567
|
* ```
|
|
@@ -562,9 +570,15 @@ export interface Module {
|
|
|
562
570
|
*/
|
|
563
571
|
getPowerManagerInfo(): Promise<PowerManagerInfo>;
|
|
564
572
|
/**
|
|
565
|
-
* API used to
|
|
573
|
+
* API used to best-effort open known Android System power manager settings for the device.
|
|
574
|
+
*
|
|
575
|
+
* Call `getPowerManagerInfo()` first to decide whether to prompt the user. A
|
|
576
|
+
* non-null `activity` means Notify Kit has a known vendor-settings candidate, not
|
|
577
|
+
* that Android has confirmed the activity exists or is accessible.
|
|
566
578
|
*
|
|
567
|
-
*
|
|
579
|
+
* Notify Kit does not require consumer apps to add `<queries>` for this helper. If
|
|
580
|
+
* Android rejects or cannot resolve a vendor settings intent, the method safely
|
|
581
|
+
* falls back or no-ops instead of crashing.
|
|
568
582
|
*
|
|
569
583
|
* View the [Background Restrictions](/react-native/android/background-restrictions) documentation for more information.
|
|
570
584
|
*
|
|
@@ -577,7 +591,7 @@ export interface Module {
|
|
|
577
591
|
* // 1. ask the user to adjust their Power Manager settings
|
|
578
592
|
* // ...
|
|
579
593
|
*
|
|
580
|
-
* // 2. if yes,
|
|
594
|
+
* // 2. if yes, try to open settings
|
|
581
595
|
* await notifee.openPowerManagerSettings();
|
|
582
596
|
* }
|
|
583
597
|
* ```
|
|
@@ -606,8 +620,8 @@ export interface Module {
|
|
|
606
620
|
*/
|
|
607
621
|
hideNotificationDrawer(): void;
|
|
608
622
|
/**
|
|
609
|
-
* Processes an FCM remote message produced by the
|
|
610
|
-
* displays a
|
|
623
|
+
* Processes an FCM remote message produced by the Notify Kit server SDK and
|
|
624
|
+
* displays a Notify Kit notification according to the embedded `notifee_options`.
|
|
611
625
|
*
|
|
612
626
|
* Safe to call from both `setBackgroundMessageHandler` and `onMessage`.
|
|
613
627
|
*
|
|
@@ -637,7 +651,7 @@ export interface Module {
|
|
|
637
651
|
*/
|
|
638
652
|
export interface ModuleStatics {
|
|
639
653
|
/**
|
|
640
|
-
* Returns the current
|
|
654
|
+
* Returns the current Notify Kit SDK version in use.
|
|
641
655
|
*/
|
|
642
656
|
SDK_VERSION: string;
|
|
643
657
|
}
|
|
@@ -167,7 +167,7 @@ export interface TriggerNotification {
|
|
|
167
167
|
trigger: Trigger;
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
|
-
* An interface representing a
|
|
170
|
+
* An interface representing a Notify Kit event.
|
|
171
171
|
*
|
|
172
172
|
* View the [Events](/react-native/events) documentation to learn more about foreground and
|
|
173
173
|
* background events.
|