react-native-notify-kit 10.9.1 → 10.10.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.
@@ -1,19 +1,18 @@
1
1
  'use strict';
2
-
2
+ Object.defineProperty(exports, '__esModule', { value: true });
3
+ exports.patchPodfileForNotifyKitNse = patchPodfileForNotifyKitNse;
4
+ const notifeeExtensionFlag_1 = require('./notifeeExtensionFlag');
3
5
  const DEFAULT_PACKAGE_PATH_FROM_IOS = '../node_modules/react-native-notify-kit';
4
6
  const RNFB_INFO_PLIST_INPUT_PATH = '$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)';
5
7
  const RNFB_POST_INSTALL_MARKER =
6
8
  'NotifyKitNSE: avoid an Xcode build cycle between the embedded app extension';
7
-
8
9
  function patchPodfileForNotifyKitNse(podfileText, options) {
9
- let patched = podfileText;
10
- let changed = false;
10
+ let patched = (0, notifeeExtensionFlag_1.ensureNotifeeExtensionFlag)(podfileText);
11
+ let changed = patched !== podfileText;
11
12
  const packagePathFromIos = options.packagePathFromIos ?? DEFAULT_PACKAGE_PATH_FROM_IOS;
12
13
  const placement = options.placement ?? 'nested';
13
14
  const useFrameworks = options.useFrameworks ?? false;
14
-
15
15
  const existingNseTarget = findUncommentedTargetBlock(patched, options.targetName);
16
-
17
16
  if (!existingNseTarget) {
18
17
  if (!hasUncommentedTarget(patched, options.targetName)) {
19
18
  const withNseTarget = insertNseTarget(
@@ -41,26 +40,20 @@ function patchPodfileForNotifyKitNse(podfileText, options) {
41
40
  changed = true;
42
41
  }
43
42
  }
44
-
45
43
  const withRnfbPatch = ensureRnfbPostInstallPatch(patched);
46
44
  if (withRnfbPatch !== patched) {
47
45
  patched = withRnfbPatch;
48
46
  changed = true;
49
47
  }
50
-
51
48
  return { contents: patched, didChange: changed };
52
49
  }
53
-
54
50
  function insertNseTarget(content, targetName, packagePathFromIos, placement, useFrameworks) {
55
51
  const block = buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrameworks);
56
-
57
52
  const targetMatch = content.match(/^target\s+['"][^'"]+['"]\s+do/m);
58
53
  if (!targetMatch || targetMatch.index === undefined) {
59
54
  return appendNseTarget(content, block, placement);
60
55
  }
61
-
62
56
  const targetEndIndex = findMatchingRubyBlockEnd(content, targetMatch.index);
63
-
64
57
  if (targetEndIndex === -1) {
65
58
  throw new Error(
66
59
  "Could not locate main app target's closing 'end' in Podfile. NSE insertion aborted. " +
@@ -68,21 +61,17 @@ function insertNseTarget(content, targetName, packagePathFromIos, placement, use
68
61
  'add the NSE target manually per the legacy guide.',
69
62
  );
70
63
  }
71
-
72
64
  if (placement === 'topLevel') {
73
65
  const insertIndex = findLineEnd(content, targetEndIndex);
74
66
  const separator = insertIndex > 0 && content[insertIndex - 1] === '\n' ? '\n' : '\n\n';
75
67
  return content.slice(0, insertIndex) + separator + block + content.slice(insertIndex);
76
68
  }
77
-
78
69
  const insertIndex = targetEndIndex;
79
70
  return content.slice(0, insertIndex) + block + content.slice(insertIndex);
80
71
  }
81
-
82
72
  function buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrameworks) {
83
73
  if (placement === 'topLevel') {
84
74
  const useFrameworksLine = buildUseFrameworksLine(useFrameworks, ' ');
85
-
86
75
  return (
87
76
  `target '${targetName}' do\n` +
88
77
  useFrameworksLine +
@@ -90,7 +79,6 @@ function buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrame
90
79
  `end\n`
91
80
  );
92
81
  }
93
-
94
82
  return (
95
83
  `\n target '${targetName}' do\n` +
96
84
  ` inherit! :search_paths\n` +
@@ -98,7 +86,6 @@ function buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrame
98
86
  ` end\n`
99
87
  );
100
88
  }
101
-
102
89
  function updateTopLevelNseTargetBlock(content, targetBlock, packagePathFromIos, useFrameworks) {
103
90
  const originalBlock = content.slice(targetBlock.startIndex, targetBlock.endIndex);
104
91
  const hasTrailingNewline = originalBlock.endsWith('\n');
@@ -106,11 +93,9 @@ function updateTopLevelNseTargetBlock(content, targetBlock, packagePathFromIos,
106
93
  ? originalBlock.slice(0, -1)
107
94
  : originalBlock;
108
95
  const lines = blockWithoutTrailingNewline.split('\n');
109
-
110
96
  if (lines.length < 2) {
111
97
  return content;
112
98
  }
113
-
114
99
  const targetLine = lines[0];
115
100
  const endLine = lines[lines.length - 1];
116
101
  const targetIndent = targetLine.match(/^[ \t]*/)?.[0] ?? '';
@@ -127,60 +112,46 @@ function updateTopLevelNseTargetBlock(content, targetBlock, packagePathFromIos,
127
112
  const updatedBlock =
128
113
  [targetLine, ...generatedLines, ...preservedBodyLines, endLine].join('\n') +
129
114
  (hasTrailingNewline ? '\n' : '');
130
-
131
115
  if (updatedBlock === originalBlock) {
132
116
  return content;
133
117
  }
134
-
135
118
  return (
136
- content.slice(0, targetBlock.startIndex) +
137
- updatedBlock +
138
- content.slice(targetBlock.endIndex)
119
+ content.slice(0, targetBlock.startIndex) + updatedBlock + content.slice(targetBlock.endIndex)
139
120
  );
140
121
  }
141
-
142
122
  function buildUseFrameworksLine(useFrameworks, indent) {
143
123
  if (useFrameworks === 'static') {
144
124
  return `${indent}use_frameworks! :linkage => :static\n`;
145
125
  }
146
-
147
126
  if (useFrameworks === 'dynamic') {
148
127
  return `${indent}use_frameworks! :linkage => :dynamic\n`;
149
128
  }
150
-
151
129
  if (useFrameworks === true) {
152
130
  return `${indent}use_frameworks!\n`;
153
131
  }
154
-
155
132
  return '';
156
133
  }
157
-
158
134
  function appendNseTarget(content, block, placement) {
159
135
  if (placement === 'nested') {
160
136
  return content + '\n' + block;
161
137
  }
162
-
163
138
  const separator = content.length === 0 ? '' : content.endsWith('\n') ? '\n' : '\n\n';
164
139
  return content + separator + block;
165
140
  }
166
-
167
141
  function findLineEnd(content, lineStartIndex) {
168
142
  const newlineIndex = content.indexOf('\n', lineStartIndex);
169
143
  return newlineIndex === -1 ? content.length : newlineIndex + 1;
170
144
  }
171
-
172
145
  function ensureRnfbPostInstallPatch(content) {
173
146
  if (content.includes(RNFB_POST_INSTALL_MARKER)) {
174
147
  return content;
175
148
  }
176
-
177
149
  const postInstall = findPostInstallBlock(content);
178
150
  if (postInstall) {
179
151
  const snippet =
180
152
  '\n' + buildRnfbPostInstallSnippet(postInstall.bodyIndent, postInstall.paramName);
181
153
  return content.slice(0, postInstall.endIndex) + snippet + content.slice(postInstall.endIndex);
182
154
  }
183
-
184
155
  const separator = content.trim().length === 0 || content.endsWith('\n') ? '\n' : '\n\n';
185
156
  return (
186
157
  content +
@@ -190,7 +161,6 @@ function ensureRnfbPostInstallPatch(content) {
190
161
  'end\n'
191
162
  );
192
163
  }
193
-
194
164
  function buildRnfbPostInstallSnippet(indent, installerParamName) {
195
165
  return [
196
166
  `${indent}# ${RNFB_POST_INSTALL_MARKER}`,
@@ -230,11 +200,9 @@ function buildRnfbPostInstallSnippet(indent, installerParamName) {
230
200
  '',
231
201
  ].join('\n');
232
202
  }
233
-
234
203
  function findPostInstallBlock(content) {
235
204
  const postInstallPattern = /^([ \t]*)post_install\s+do\s+\|([^|]+)\|\s*(?:#.*)?$/gm;
236
205
  let match;
237
-
238
206
  while ((match = postInstallPattern.exec(content)) !== null) {
239
207
  const endIndex = findMatchingRubyBlockEnd(content, match.index);
240
208
  if (endIndex !== -1) {
@@ -245,96 +213,75 @@ function findPostInstallBlock(content) {
245
213
  };
246
214
  }
247
215
  }
248
-
249
216
  return null;
250
217
  }
251
-
252
218
  function findMatchingRubyBlockEnd(content, startIndex) {
253
219
  const afterStart = content.slice(startIndex);
254
220
  const lines = afterStart.split('\n');
255
221
  let depth = 0;
256
222
  let charIndex = startIndex;
257
-
258
223
  for (const line of lines) {
259
224
  const trimmed = stripRubyLineComment(line).trim();
260
-
261
225
  depth += countRubyBlockOpeners(trimmed);
262
-
263
226
  if (trimmed === 'end') {
264
227
  depth--;
265
228
  if (depth === 0) {
266
229
  return charIndex;
267
230
  }
268
231
  }
269
-
270
232
  charIndex += line.length + 1;
271
233
  }
272
-
273
234
  return -1;
274
235
  }
275
-
276
236
  function countRubyBlockOpeners(line) {
277
237
  if (line.length === 0) {
278
238
  return 0;
279
239
  }
280
-
281
240
  const startsWithKeywordBlock = /^(if|unless|case|begin|while|until|for|def|class|module)\b/.test(
282
241
  line,
283
242
  );
284
243
  if (startsWithKeywordBlock) {
285
244
  return 1;
286
245
  }
287
-
288
246
  if (/\bdo\b(\s*\|[^|]*\|)?\s*$/.test(line)) {
289
247
  return 1;
290
248
  }
291
-
292
249
  return 0;
293
250
  }
294
-
295
251
  function stripRubyLineComment(line) {
296
252
  return line.replace(/#.*$/, '');
297
253
  }
298
-
299
254
  function findUncommentedTargetBlock(content, targetName) {
300
255
  const pattern = new RegExp(
301
256
  `^[ \\t]*target\\s+['"]${escapeRegex(targetName)}['"]\\s+do\\b.*$`,
302
257
  'gm',
303
258
  );
304
259
  let match;
305
-
306
260
  while ((match = pattern.exec(content)) !== null) {
307
261
  const line = match[0];
308
262
  if (stripRubyLineComment(line).trim().length === 0) {
309
263
  continue;
310
264
  }
311
-
312
265
  const endLineStart = findMatchingRubyBlockEnd(content, match.index);
313
266
  if (endLineStart === -1) {
314
267
  return null;
315
268
  }
316
-
317
269
  return {
318
270
  startIndex: match.index,
319
271
  endIndex: findLineEnd(content, endLineStart),
320
272
  };
321
273
  }
322
-
323
274
  return null;
324
275
  }
325
-
326
276
  function isUncommentedUseFrameworksLine(line) {
327
277
  return /^use_frameworks!(?:\s|$)/.test(stripRubyLineComment(line).trim());
328
278
  }
329
-
330
279
  function isUncommentedRnNotifeeCorePodLine(line) {
331
280
  return /^pod\s+['"]RNNotifeeCore['"](?:\s|,|$)/.test(stripRubyLineComment(line).trim());
332
281
  }
333
-
334
282
  function isUncommentedSearchPathInheritanceLine(line) {
335
283
  return /^inherit!\s+:search_paths\b/.test(stripRubyLineComment(line).trim());
336
284
  }
337
-
338
285
  function hasUncommentedTarget(content, targetName) {
339
286
  const pattern = new RegExp(`target\\s+['"]${escapeRegex(targetName)}['"]`);
340
287
  for (const line of content.split('\n')) {
@@ -345,11 +292,6 @@ function hasUncommentedTarget(content, targetName) {
345
292
  }
346
293
  return false;
347
294
  }
348
-
349
295
  function escapeRegex(s) {
350
296
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
351
297
  }
352
-
353
- module.exports = {
354
- patchPodfileForNotifyKitNse,
355
- };
@@ -553,6 +553,14 @@ export default class NotifeeApiModule extends NotifeeNativeModule implements Mod
553
553
  return Promise.resolve();
554
554
  };
555
555
 
556
+ public shouldShowRequestPermissionRationale = (): Promise<boolean> => {
557
+ if (isAndroid) {
558
+ return this.native.shouldShowRequestPermissionRationale();
559
+ }
560
+
561
+ return Promise.resolve(false);
562
+ };
563
+
556
564
  public requestPermission = (
557
565
  permissions: IOSNotificationPermissions = {},
558
566
  ): Promise<NotificationSettings> => {
@@ -26,6 +26,7 @@ export interface Spec extends TurboModule {
26
26
  createTriggerNotification(notification: Object, trigger: Object): Promise<void>;
27
27
  requestPermission(permissions: Object): Promise<Object>;
28
28
  getNotificationSettings(): Promise<Object>;
29
+ shouldShowRequestPermissionRationale(): Promise<boolean>;
29
30
  getInitialNotification(): Promise<Object | null>;
30
31
 
31
32
  // ─── Android-only ─────────────────────────────────────────────────────────
@@ -504,6 +504,26 @@ export interface Module {
504
504
  */
505
505
  getNotificationSettings(): Promise<NotificationSettings>;
506
506
 
507
+ /**
508
+ * Query Android's current recommendation to show explanatory UI before requesting
509
+ * `POST_NOTIFICATIONS`. This does not request permission or change request history.
510
+ *
511
+ * On Android 13+ (API 33+), resolves the current Activity's platform rationale result.
512
+ * `false` means Android does not recommend rationale UI; it does not prove permanent
513
+ * denial or whether another permission dialog can appear. It can also occur before
514
+ * the first request or when permission is already granted. Do not infer dialog
515
+ * eligibility from this result combined with `authorizationStatus` or request history.
516
+ *
517
+ * On Android 13+ without a current Activity, rejects with code `ERR_NO_ACTIVITY`.
518
+ * Other native query failures reject. Retry when an Activity is available.
519
+ * On Android below API 33 and on other platforms, resolves `false` (not applicable).
520
+ * Each call queries current state; query again after returning from Settings.
521
+ * Target SDK, permission declarations and system policy affect platform behavior.
522
+ *
523
+ * @platform android
524
+ */
525
+ shouldShowRequestPermissionRationale(): Promise<boolean>;
526
+
507
527
  /**
508
528
  * Get the current badge count value for this application on the current device.
509
529
  *
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '10.9.1';
2
+ export const version = '10.10.1';