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.
Files changed (52) hide show
  1. package/README.md +99 -96
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/AndroidManifest.xml +0 -1
  4. package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
  5. package/android/src/main/java/app/notifee/core/NotificationManager.java +21 -8
  6. package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
  7. package/android/src/main/java/app/notifee/core/ReceiverService.java +18 -13
  8. package/android/src/main/java/app/notifee/core/model/NotificationAndroidActionModel.java +1 -2
  9. package/android/src/main/java/app/notifee/core/model/NotificationAndroidPressActionModel.java +3 -9
  10. package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
  11. package/android/src/main/java/app/notifee/core/utility/IntentUtils.java +0 -28
  12. package/android/src/main/java/app/notifee/core/utility/PowerManagerUtils.java +79 -41
  13. package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +5 -1
  14. package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
  15. package/android/src/main/kotlin/io/invertase/notifee/NotifeeReactUtils.kt +1 -2
  16. package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +150 -0
  17. package/cli/dist/lib/patchPodfile.d.ts +3 -1
  18. package/cli/dist/lib/patchPodfile.js +125 -33
  19. package/cli/dist/lib/patchPodfile.js.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/types/Module.d.ts +27 -13
  22. package/dist/types/Notification.d.ts +1 -1
  23. package/dist/types/NotificationIOS.d.ts +44 -21
  24. package/dist/types/NotificationIOS.js +15 -1
  25. package/dist/types/NotificationIOS.js.map +1 -1
  26. package/dist/types/PowerManagerInfo.d.ts +9 -4
  27. package/dist/types/Trigger.d.ts +45 -2
  28. package/dist/types/Trigger.js +22 -0
  29. package/dist/types/Trigger.js.map +1 -1
  30. package/dist/validators/validateIOSCategory.js +2 -2
  31. package/dist/validators/validateIOSCategory.js.map +1 -1
  32. package/dist/validators/validateTrigger.js +26 -1
  33. package/dist/validators/validateTrigger.js.map +1 -1
  34. package/dist/version.d.ts +1 -1
  35. package/dist/version.js +1 -1
  36. package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +20 -10
  37. package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +1 -2
  38. package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +44 -35
  39. package/ios/NotifeeCore/NotifeeCore.m +1042 -119
  40. package/ios/NotifeeCore/NotifeeCoreUtil.h +36 -1
  41. package/ios/NotifeeCore/NotifeeCoreUtil.m +533 -9
  42. package/ios/RNNotifee/NotifeeApiModule.mm +2 -2
  43. package/package.json +1 -1
  44. package/src/index.ts +2 -0
  45. package/src/types/Module.ts +27 -13
  46. package/src/types/Notification.ts +1 -1
  47. package/src/types/NotificationIOS.ts +43 -28
  48. package/src/types/PowerManagerInfo.ts +9 -4
  49. package/src/types/Trigger.ts +45 -1
  50. package/src/validators/validateIOSCategory.ts +4 -2
  51. package/src/validators/validateTrigger.ts +38 -0
  52. package/src/version.ts +1 -1
@@ -543,20 +543,20 @@ export interface Module {
543
543
  /**
544
544
  * API used to configure iOS notification handling behavior.
545
545
  *
546
- * Use this to control whether Notifee should handle remote (push) notifications
546
+ * Use this to control whether Notify Kit should handle remote (push) notifications
547
547
  * on iOS. When `handleRemoteNotifications` is set to `false`, remote notifications
548
548
  * (e.g. from Firebase Cloud Messaging) will be forwarded to the original
549
- * notification delegate instead of being processed by Notifee.
549
+ * notification delegate instead of being processed by Notify Kit.
550
550
  *
551
551
  * This allows libraries like React Native Firebase Messaging to receive tap events
552
552
  * via `onNotificationOpenedApp()` and `getInitialNotification()`.
553
553
  *
554
- * Defaults to `true` (Notifee handles all notifications) for backward compatibility.
554
+ * Defaults to `true` (Notify Kit handles all notifications) for backward compatibility.
555
555
  *
556
556
  * ```js
557
557
  * import notifee from 'react-native-notify-kit';
558
558
  *
559
- * // Disable Notifee handling of remote notifications
559
+ * // Disable Notify Kit handling of remote notifications
560
560
  * await notifee.setNotificationConfig({
561
561
  * ios: { handleRemoteNotifications: false },
562
562
  * });
@@ -590,9 +590,17 @@ export interface Module {
590
590
  isBatteryOptimizationEnabled(): Promise<boolean>;
591
591
 
592
592
  /**
593
- * API used to get information about the device and its power manager settings, including manufacturer, model, version and activity.
593
+ * API used to get best-effort information about the device and its power manager settings, including manufacturer, model, version and a known activity candidate.
594
594
  *
595
- * If `activity` is `null`, `openPowerManagerSettings()` will be noop.
595
+ * The returned `activity` is based on Notify Kit's manufacturer mapping and is not
596
+ * prevalidated with `PackageManager`. A non-null value does not guarantee that
597
+ * `openPowerManagerSettings()` can open that screen on the current device firmware.
598
+ *
599
+ * Notify Kit does not rely on Android 11+ package-visibility queries for this helper,
600
+ * so consumer apps do not need to add `<queries>` to use it.
601
+ *
602
+ * If `activity` is `null`, `openPowerManagerSettings()` will be a no-op because
603
+ * there is no known vendor-settings candidate.
596
604
  *
597
605
  * On iOS, an instance of `PowerManagerInfo` will be returned with `activity` set to `null`.
598
606
  *
@@ -607,7 +615,7 @@ export interface Module {
607
615
  * // 1. ask the user to adjust their Power Manager settings
608
616
  * // ...
609
617
  *
610
- * // 2. open settings
618
+ * // 2. open settings best-effort
611
619
  * await notifee.openPowerManagerSettings();
612
620
  * }
613
621
  * ```
@@ -617,9 +625,15 @@ export interface Module {
617
625
  getPowerManagerInfo(): Promise<PowerManagerInfo>;
618
626
 
619
627
  /**
620
- * API used to navigate to the appropriate Android System settings for the device.
628
+ * API used to best-effort open known Android System power manager settings for the device.
629
+ *
630
+ * Call `getPowerManagerInfo()` first to decide whether to prompt the user. A
631
+ * non-null `activity` means Notify Kit has a known vendor-settings candidate, not
632
+ * that Android has confirmed the activity exists or is accessible.
621
633
  *
622
- * Call `getPowerManagerInfo()` first to find out if the user's device is supported.
634
+ * Notify Kit does not require consumer apps to add `<queries>` for this helper. If
635
+ * Android rejects or cannot resolve a vendor settings intent, the method safely
636
+ * falls back or no-ops instead of crashing.
623
637
  *
624
638
  * View the [Background Restrictions](/react-native/android/background-restrictions) documentation for more information.
625
639
  *
@@ -632,7 +646,7 @@ export interface Module {
632
646
  * // 1. ask the user to adjust their Power Manager settings
633
647
  * // ...
634
648
  *
635
- * // 2. if yes, navigate them to settings
649
+ * // 2. if yes, try to open settings
636
650
  * await notifee.openPowerManagerSettings();
637
651
  * }
638
652
  * ```
@@ -663,8 +677,8 @@ export interface Module {
663
677
  hideNotificationDrawer(): void;
664
678
 
665
679
  /**
666
- * Processes an FCM remote message produced by the NotifyKit server SDK and
667
- * displays a Notifee notification according to the embedded `notifee_options`.
680
+ * Processes an FCM remote message produced by the Notify Kit server SDK and
681
+ * displays a Notify Kit notification according to the embedded `notifee_options`.
668
682
  *
669
683
  * Safe to call from both `setBackgroundMessageHandler` and `onMessage`.
670
684
  *
@@ -696,7 +710,7 @@ export interface Module {
696
710
  */
697
711
  export interface ModuleStatics {
698
712
  /**
699
- * Returns the current Notifee SDK version in use.
713
+ * Returns the current Notify Kit SDK version in use.
700
714
  */
701
715
  SDK_VERSION: string;
702
716
  }
@@ -192,7 +192,7 @@ export interface TriggerNotification {
192
192
  }
193
193
 
194
194
  /**
195
- * An interface representing a Notifee event.
195
+ * An interface representing a Notify Kit event.
196
196
  *
197
197
  * View the [Events](/react-native/events) documentation to learn more about foreground and
198
198
  * background events.
@@ -79,25 +79,20 @@ export interface NotificationIOS {
79
79
  threadId?: string;
80
80
 
81
81
  /**
82
- * The argument that is inserted in the IOSCategory.summaryFormat for this notification.
83
- *
84
- * See `IOSCategory.summaryFormat`.
82
+ * Kept for compatibility. No-op on supported iOS versions because notification summary
83
+ * arguments are ignored by iOS 15+.
85
84
  *
86
85
  * @platform ios iOS >= 12
86
+ * @deprecated May be removed in a future major release.
87
87
  */
88
88
  summaryArgument?: string;
89
89
 
90
90
  /**
91
- * A number that indicates how many items in the summary are being represented.
92
- *
93
- * For example if a messages app sends one notification for 3 new messages in a group chat,
94
- * the summaryArgument could be the name of the group chat and the summaryArgumentCount should be 3.
95
- *
96
- * If set, value cannot be 0 or less.
97
- *
98
- * See `IOSCategory.summaryFormat`.
91
+ * Kept for compatibility. No-op on supported iOS versions because notification summary
92
+ * arguments are ignored by iOS 15+.
99
93
  *
100
94
  * @platform ios iOS >= 12
95
+ * @deprecated May be removed in a future major release.
101
96
  */
102
97
  summaryArgumentCount?: number;
103
98
 
@@ -113,7 +108,7 @@ export interface NotificationIOS {
113
108
  /**
114
109
  * Optional property to customise how notifications are presented when the app is in the foreground.
115
110
  *
116
- * By default, Notifee will show iOS notifications in heads-up mode if your app is currently in the foreground.
111
+ * By default, Notify Kit will show iOS notifications in heads-up mode if your app is currently in the foreground.
117
112
  */
118
113
  foregroundPresentationOptions?: IOSForegroundPresentationOptions;
119
114
 
@@ -147,7 +142,7 @@ export interface IOSCommunicationInfoPerson {
147
142
  /**
148
143
  * An interface to customise how notifications are shown when the app is in the foreground.
149
144
  *
150
- * By default, Notifee will show iOS notifications in heads-up mode if your app is currently in the foreground.
145
+ * By default, Notify Kit will show iOS notifications in heads-up mode if your app is currently in the foreground.
151
146
  *
152
147
  * View the [Foreground Notifications](/react-native/ios/appearance#foreground-notifications) to learn
153
148
  * more.
@@ -180,8 +175,6 @@ export interface IOSForegroundPresentationOptions {
180
175
  /**
181
176
  * Present the notification as a banner
182
177
  *
183
- * For iOS 13 and lower, will be equivalent to setting `alert` to true
184
- *
185
178
  * Defaults to true
186
179
  */
187
180
  banner?: boolean;
@@ -189,8 +182,6 @@ export interface IOSForegroundPresentationOptions {
189
182
  /**
190
183
  * Show the notification in Notification Center
191
184
  *
192
- * For iOS 13 and lower, will be equivalent to setting `alert` to true
193
- *
194
185
  * Defaults to true
195
186
  */
196
187
  list?: boolean;
@@ -254,18 +245,20 @@ export interface IOSNotificationPermissions {
254
245
  provisional?: boolean;
255
246
 
256
247
  /**
257
- * Request permission for Siri to automatically read out notification messages over AirPods.
248
+ * Explicit announcement authorization requests are no longer needed because announcement
249
+ * authorization is included by iOS on supported versions. Kept for API compatibility.
258
250
  *
259
251
  * Defaults to false.
260
252
  *
261
253
  * @platform ios iOS >= 13
254
+ * @deprecated May be removed in a future major release.
262
255
  */
263
256
  announcement?: boolean;
264
257
 
265
258
  // TODO later version
266
259
  // /**
267
260
  // * Using this permission indicates to iOS that it should display a button for in-app notification
268
- // * settings. Pressing this button when your application is open will trigger a Notifee
261
+ // * settings. Pressing this button when your application is open will trigger a Notify Kit
269
262
  // * 'ACTION_PRESS' event with a `pressAction.id` of 'notification-settings'
270
263
  // * (or via getInitialNotification 'pressAction.id' when app launched)
271
264
  // *
@@ -402,13 +395,28 @@ export interface IOSNotificationSettings {
402
395
  }
403
396
 
404
397
  /**
405
- * TODO docs, used to provide context to Siri
398
+ * Intent identifiers used to provide category context to Siri.
406
399
  *
407
400
  * @platform ios
408
401
  */
409
402
  export enum IOSIntentIdentifier {
403
+ /**
404
+ * Start a call intent.
405
+ *
406
+ * Maps to Apple's unified `INStartCallIntentIdentifier`.
407
+ */
408
+ START_CALL = 25,
409
+
410
+ /**
411
+ * @deprecated Use `START_CALL` instead. Apple deprecated the separate audio call
412
+ * intent identifier in favor of a unified start call identifier.
413
+ */
410
414
  START_AUDIO_CALL = 0,
411
415
 
416
+ /**
417
+ * @deprecated Use `START_CALL` instead. Apple deprecated the separate video call
418
+ * intent identifier in favor of a unified start call identifier.
419
+ */
412
420
  START_VIDEO_CALL = 1,
413
421
 
414
422
  SEARCH_CALL_HISTORY = 2,
@@ -487,14 +495,13 @@ export interface IOSNotificationCategory {
487
495
  */
488
496
  allowInCarPlay?: boolean;
489
497
 
490
- /*
491
- * Allow notifications in this category to be announced to the user
492
- * via 3rd party services such as Siri.
493
- *
494
- * For example, if the notification can be automatically read by Siri
495
- * while the user is wearing AirPods.
498
+ /**
499
+ * Kept for compatibility. No-op on supported iOS versions because announcement category
500
+ * options are ignored by iOS 15+.
496
501
  *
497
502
  * Defaults to `false`.
503
+ *
504
+ * @deprecated May be removed in a future major release.
498
505
  */
499
506
  allowAnnouncement?: boolean;
500
507
 
@@ -519,6 +526,14 @@ export interface IOSNotificationCategory {
519
526
  */
520
527
  hiddenPreviewsBodyPlaceholder?: string;
521
528
 
529
+ /**
530
+ * Intent identifiers used by the system to provide category context to Siri.
531
+ *
532
+ * Use `IOSIntentIdentifier.START_CALL` for call categories. Legacy
533
+ * `START_AUDIO_CALL` and `START_VIDEO_CALL` values remain accepted for source
534
+ * compatibility, but both map to Apple's unified start call intent identifier.
535
+ * Categories read back from iOS can return `START_CALL` for call intents.
536
+ */
522
537
  intentIdentifiers?: IOSIntentIdentifier[];
523
538
 
524
539
  /*
@@ -689,11 +704,11 @@ export type IOSNotificationInterruptionLevel = 'active' | 'critical' | 'passive'
689
704
  */
690
705
  export interface IOSNotificationConfig {
691
706
  /**
692
- * Whether Notifee should handle remote (push) notifications on iOS.
707
+ * Whether Notify Kit should handle remote (push) notifications on iOS.
693
708
  *
694
709
  * When set to `false`, remote notifications (e.g. from Firebase Cloud Messaging)
695
710
  * will be forwarded to the original notification delegate instead of being
696
- * processed by Notifee. This allows libraries like React Native Firebase
711
+ * processed by Notify Kit. This allows libraries like React Native Firebase
697
712
  * Messaging to receive tap events via `onNotificationOpenedApp()` and
698
713
  * `getInitialNotification()`.
699
714
  *
@@ -32,12 +32,17 @@ export interface PowerManagerInfo {
32
32
  version?: string;
33
33
 
34
34
  /**
35
- * The activity that the user will be navigated to if `openPowerManagerSettings()` is called.
35
+ * The known vendor-settings activity candidate for this device manufacturer.
36
36
  *
37
- * Use this as an indicator of what steps the user may have to perform,
38
- * in-order to prevent your app from being killed.
37
+ * This value is based on Notify Kit's manufacturer mapping. It is not prevalidated
38
+ * with `PackageManager`, and it is not a guarantee that the activity is installed
39
+ * or accessible on the current device firmware.
39
40
  *
40
- * If no activity can be found, value will be null.
41
+ * Use this as a best-effort indicator of what steps the user may have to perform,
42
+ * in-order to prevent your app from being killed. `openPowerManagerSettings()`
43
+ * handles unavailable or rejected candidates safely.
44
+ *
45
+ * If no known activity candidate exists, value will be null.
41
46
  */
42
47
  activity?: string | null;
43
48
  }
@@ -21,13 +21,35 @@ export interface TimestampTrigger {
21
21
  * if set to `RepeatFrequency.HOURLY`, the notification will repeat every hour from the timestamp specified.
22
22
  * if set to `RepeatFrequency.DAILY`, the notification will repeat every day from the timestamp specified.
23
23
  * if set to `RepeatFrequency.WEEKLY`, the notification will repeat every week from the timestamp specified.
24
+ * if set to `RepeatFrequency.MONTHLY`, the notification will repeat every calendar month from the timestamp specified.
25
+ *
26
+ * Yearly recurrence is not supported.
24
27
  */
25
28
  repeatFrequency?: RepeatFrequency;
26
29
 
30
+ /**
31
+ * Multiplier applied to `repeatFrequency` for timestamp triggers.
32
+ *
33
+ * For example, `repeatFrequency: RepeatFrequency.DAILY` with
34
+ * `repeatInterval: 2` repeats every 2 days. `RepeatFrequency.WEEKLY`
35
+ * with `repeatInterval: 2` repeats every 2 weeks, and
36
+ * `RepeatFrequency.MONTHLY` with `repeatInterval: 3` repeats every
37
+ * 3 months.
38
+ *
39
+ * Valid only when `repeatFrequency` is set to a repeating value. It is
40
+ * not valid without `repeatFrequency` or with `RepeatFrequency.NONE`.
41
+ * Must be a positive integer.
42
+ *
43
+ * Defaults to `1` when `repeatFrequency` is set.
44
+ */
45
+ repeatInterval?: number;
46
+
27
47
  /**
28
48
  * Choose to schedule your trigger notification with Android's AlarmManager API.
29
49
  *
30
- * By default, trigger notifications are created with Android's WorkManager API.
50
+ * By default, timestamp trigger notifications use AlarmManager on Android. Set
51
+ * this to `false` to opt out to WorkManager. `RepeatFrequency.MONTHLY` is not
52
+ * supported when this is `false`.
31
53
  *
32
54
  * @platform android
33
55
  */
@@ -71,14 +93,36 @@ export interface TimestampTriggerAlarmManager {
71
93
 
72
94
  /**
73
95
  * An interface representing the different frequencies which can be used with `TimestampTrigger.repeatFrequency`.
96
+ * Supported timestamp repeat frequencies are hourly, daily, weekly, and monthly.
97
+ * Yearly recurrence is not supported.
74
98
  *
75
99
  * View the [Triggers](/react-native/triggers) documentation to learn more.
76
100
  */
77
101
  export enum RepeatFrequency {
102
+ /**
103
+ * Do not repeat. `TimestampTrigger.repeatInterval` cannot be used with `NONE`.
104
+ */
78
105
  NONE = -1,
106
+ /**
107
+ * Repeat every calendar hour from the timestamp.
108
+ */
79
109
  HOURLY = 0,
110
+ /**
111
+ * Repeat every calendar day from the timestamp.
112
+ */
80
113
  DAILY = 1,
114
+ /**
115
+ * Repeat every calendar week from the timestamp.
116
+ */
81
117
  WEEKLY = 2,
118
+ /**
119
+ * Repeat every calendar month from the timestamp.
120
+ *
121
+ * Use `TimestampTrigger.repeatInterval` for intervals such as every 3 months.
122
+ * Monthly repeats use native calendar semantics; dates that do not exist in a
123
+ * target month are adjusted by the platform calendar.
124
+ */
125
+ MONTHLY = 3,
82
126
  }
83
127
 
84
128
  /**
@@ -110,12 +110,14 @@ export default function validateIOSCategory(
110
110
  throw new Error("'category.intentIdentifiers' expected an array value.");
111
111
  }
112
112
 
113
- const identifiers = Object.values(IOSIntentIdentifier);
113
+ const identifiers = Object.values(IOSIntentIdentifier).filter(
114
+ (identifier): identifier is IOSIntentIdentifier => typeof identifier === 'number',
115
+ );
114
116
 
115
117
  for (let i = 0; i < category.intentIdentifiers.length; i++) {
116
118
  const intentIdentifier = category.intentIdentifiers[i];
117
119
 
118
- if (!identifiers.includes(intentIdentifier)) {
120
+ if (typeof intentIdentifier !== 'number' || !identifiers.includes(intentIdentifier)) {
119
121
  throw new Error(
120
122
  `'category.intentIdentifiers' unexpected intentIdentifier "${intentIdentifier}" at array index "${i}".`,
121
123
  );
@@ -9,6 +9,7 @@ import {
9
9
  isValidEnum,
10
10
  isUndefined,
11
11
  isBoolean,
12
+ isAndroid,
12
13
  } from '../utils';
13
14
  import {
14
15
  Trigger,
@@ -100,6 +101,33 @@ function validateTimestampTrigger(trigger: TimestampTrigger): TimestampTrigger {
100
101
  out.repeatFrequency = trigger.repeatFrequency;
101
102
  }
102
103
 
104
+ const hasRepeatFrequency =
105
+ objectHasProperty(trigger, 'repeatFrequency') && !isUndefined(trigger.repeatFrequency);
106
+ const isRepeating = hasRepeatFrequency && trigger.repeatFrequency !== RepeatFrequency.NONE;
107
+
108
+ if (objectHasProperty(trigger, 'repeatInterval') && !isUndefined(trigger.repeatInterval)) {
109
+ if (!hasRepeatFrequency) {
110
+ throw new Error("'trigger.repeatInterval' requires a repeatFrequency value.");
111
+ }
112
+
113
+ if (trigger.repeatFrequency === RepeatFrequency.NONE) {
114
+ throw new Error("'trigger.repeatInterval' requires a repeating repeatFrequency value.");
115
+ }
116
+
117
+ if (
118
+ !isNumber(trigger.repeatInterval) ||
119
+ !Number.isFinite(trigger.repeatInterval) ||
120
+ !Number.isInteger(trigger.repeatInterval) ||
121
+ trigger.repeatInterval <= 0
122
+ ) {
123
+ throw new Error("'trigger.repeatInterval' expected a positive integer value.");
124
+ }
125
+
126
+ out.repeatInterval = trigger.repeatInterval;
127
+ } else if (isRepeating) {
128
+ out.repeatInterval = 1;
129
+ }
130
+
103
131
  if (objectHasProperty(trigger, 'alarmManager') && !isUndefined(trigger.alarmManager)) {
104
132
  if (isBoolean(trigger.alarmManager)) {
105
133
  if (trigger.alarmManager) {
@@ -118,6 +146,16 @@ function validateTimestampTrigger(trigger: TimestampTrigger): TimestampTrigger {
118
146
  out.alarmManager = validateTimestampAlarmManager();
119
147
  }
120
148
 
149
+ if (
150
+ isAndroid &&
151
+ trigger.alarmManager === false &&
152
+ out.repeatFrequency === RepeatFrequency.MONTHLY
153
+ ) {
154
+ throw new Error(
155
+ "'trigger.repeatFrequency' MONTHLY is not supported when 'trigger.alarmManager' is false.",
156
+ );
157
+ }
158
+
121
159
  return out;
122
160
  }
123
161
 
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '10.1.0';
2
+ export const version = '10.2.1';