expo-notifications 1.0.0-canary-20241021-7aba813 → 1.0.0-canary-20250122-166c2cb

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 (126) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/notifications/notifications/NotificationSerializer.java +2 -0
  4. package/android/src/main/java/expo/modules/notifications/notifications/RemoteMessageSerializer.java +2 -1
  5. package/android/src/main/java/expo/modules/notifications/notifications/background/BackgroundRemoteNotificationTaskConsumer.java +5 -0
  6. package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java +10 -0
  7. package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationData.kt +69 -0
  8. package/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt +20 -30
  9. package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt +39 -25
  10. package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoHandlingDelegate.kt +4 -4
  11. package/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt +10 -2
  12. package/build/DevicePushTokenAutoRegistration.fx.d.ts +2 -0
  13. package/build/DevicePushTokenAutoRegistration.fx.d.ts.map +1 -1
  14. package/build/DevicePushTokenAutoRegistration.fx.js +2 -0
  15. package/build/DevicePushTokenAutoRegistration.fx.js.map +1 -1
  16. package/build/NotificationChannelGroupManager.types.d.ts +2 -2
  17. package/build/NotificationChannelGroupManager.types.js.map +1 -1
  18. package/build/NotificationChannelManager.types.d.ts +2 -6
  19. package/build/NotificationChannelManager.types.d.ts.map +1 -1
  20. package/build/NotificationChannelManager.types.js +0 -4
  21. package/build/NotificationChannelManager.types.js.map +1 -1
  22. package/build/NotificationPermissions.types.d.ts +1 -2
  23. package/build/NotificationPermissions.types.d.ts.map +1 -1
  24. package/build/NotificationPermissions.types.js.map +1 -1
  25. package/build/Notifications.types.d.ts +29 -24
  26. package/build/Notifications.types.d.ts.map +1 -1
  27. package/build/Notifications.types.js +1 -0
  28. package/build/Notifications.types.js.map +1 -1
  29. package/build/NotificationsEmitter.d.ts +13 -4
  30. package/build/NotificationsEmitter.d.ts.map +1 -1
  31. package/build/NotificationsEmitter.js +6 -6
  32. package/build/NotificationsEmitter.js.map +1 -1
  33. package/build/NotificationsHandler.d.ts +1 -1
  34. package/build/NotificationsHandler.js.map +1 -1
  35. package/build/TokenEmitter.d.ts +1 -1
  36. package/build/TokenEmitter.d.ts.map +1 -1
  37. package/build/TokenEmitter.js +3 -1
  38. package/build/TokenEmitter.js.map +1 -1
  39. package/build/Tokens.types.d.ts +2 -2
  40. package/build/Tokens.types.js.map +1 -1
  41. package/build/getDevicePushTokenAsync.d.ts.map +1 -1
  42. package/build/getDevicePushTokenAsync.js +2 -0
  43. package/build/getDevicePushTokenAsync.js.map +1 -1
  44. package/build/getExpoPushTokenAsync.d.ts.map +1 -1
  45. package/build/getExpoPushTokenAsync.js +4 -1
  46. package/build/getExpoPushTokenAsync.js.map +1 -1
  47. package/build/presentNotificationAsync.d.ts +2 -1
  48. package/build/presentNotificationAsync.d.ts.map +1 -1
  49. package/build/presentNotificationAsync.js +2 -1
  50. package/build/presentNotificationAsync.js.map +1 -1
  51. package/build/registerTaskAsync.d.ts +9 -4
  52. package/build/registerTaskAsync.d.ts.map +1 -1
  53. package/build/registerTaskAsync.js +9 -4
  54. package/build/registerTaskAsync.js.map +1 -1
  55. package/build/scheduleNotificationAsync.d.ts +3 -1
  56. package/build/scheduleNotificationAsync.d.ts.map +1 -1
  57. package/build/scheduleNotificationAsync.js +7 -3
  58. package/build/scheduleNotificationAsync.js.map +1 -1
  59. package/build/setBadgeCountAsync.d.ts +1 -1
  60. package/build/setBadgeCountAsync.js +1 -1
  61. package/build/setBadgeCountAsync.js.map +1 -1
  62. package/build/setNotificationChannelAsync.d.ts +2 -0
  63. package/build/setNotificationChannelAsync.d.ts.map +1 -1
  64. package/build/setNotificationChannelAsync.js +2 -0
  65. package/build/setNotificationChannelAsync.js.map +1 -1
  66. package/build/useLastNotificationResponse.d.ts +4 -4
  67. package/build/useLastNotificationResponse.d.ts.map +1 -1
  68. package/build/useLastNotificationResponse.js +3 -1
  69. package/build/useLastNotificationResponse.js.map +1 -1
  70. package/build/warnOfExpoGoPushUsage.d.ts +2 -0
  71. package/build/warnOfExpoGoPushUsage.d.ts.map +1 -0
  72. package/build/warnOfExpoGoPushUsage.js +9 -0
  73. package/build/warnOfExpoGoPushUsage.js.map +1 -0
  74. package/expo-module.config.json +4 -0
  75. package/ios/EXNotifications/Badge/BadgeModule.swift +28 -0
  76. package/ios/EXNotifications/Building/NotificationBuilder.swift +147 -0
  77. package/ios/EXNotifications/Notifications/EXNotificationCenterDelegate.h +3 -2
  78. package/ios/EXNotifications/Notifications/EXNotificationCenterDelegate.m +12 -35
  79. package/ios/EXNotifications/Notifications/NotificationCenterManager.swift +134 -0
  80. package/ios/EXNotifications/Notifications/Presenting/PresentationModule.swift +81 -0
  81. package/ios/EXNotifications/Notifications/Scheduling/SchedulerModule.swift +302 -0
  82. package/ios/EXNotifications/PushToken/PushTokenAppDelegateSubscriber.swift +18 -0
  83. package/ios/EXNotifications/PushToken/PushTokenModule.swift +51 -0
  84. package/ios/EXNotifications/ServerRegistration/ServerRegistrationModule.swift +179 -0
  85. package/ios/EXNotifications.podspec +7 -1
  86. package/package.json +8 -12
  87. package/plugin/build/withNotifications.d.ts +8 -0
  88. package/plugin/build/withNotificationsIOS.d.ts +0 -3
  89. package/plugin/build/withNotificationsIOS.js +24 -4
  90. package/plugin/src/withNotifications.ts +9 -0
  91. package/plugin/src/withNotificationsIOS.ts +35 -2
  92. package/src/DevicePushTokenAutoRegistration.fx.ts +2 -0
  93. package/src/NotificationChannelGroupManager.types.ts +2 -2
  94. package/src/NotificationChannelManager.types.ts +2 -6
  95. package/src/NotificationPermissions.types.ts +1 -3
  96. package/src/Notifications.types.ts +35 -31
  97. package/src/NotificationsEmitter.ts +6 -6
  98. package/src/NotificationsHandler.ts +1 -1
  99. package/src/TokenEmitter.ts +3 -1
  100. package/src/Tokens.types.ts +2 -2
  101. package/src/getDevicePushTokenAsync.ts +2 -0
  102. package/src/getExpoPushTokenAsync.ts +5 -1
  103. package/src/presentNotificationAsync.ts +2 -1
  104. package/src/registerTaskAsync.ts +9 -4
  105. package/src/scheduleNotificationAsync.ts +9 -3
  106. package/src/setBadgeCountAsync.ts +1 -1
  107. package/src/setNotificationChannelAsync.ts +2 -0
  108. package/src/useLastNotificationResponse.ts +4 -4
  109. package/src/warnOfExpoGoPushUsage.ts +12 -0
  110. package/ios/EXNotifications/Building/EXNotificationBuilder.h +0 -19
  111. package/ios/EXNotifications/Building/EXNotificationBuilder.m +0 -105
  112. package/ios/EXNotifications/EXBadgeModule.h +0 -11
  113. package/ios/EXNotifications/EXBadgeModule.m +0 -36
  114. package/ios/EXNotifications/EXServerRegistrationModule.h +0 -19
  115. package/ios/EXNotifications/EXServerRegistrationModule.m +0 -195
  116. package/ios/EXNotifications/Notifications/NSDictionary+EXNotificationsVerifyingClass.h +0 -7
  117. package/ios/EXNotifications/Notifications/NSDictionary+EXNotificationsVerifyingClass.m +0 -19
  118. package/ios/EXNotifications/Notifications/Presenting/EXNotificationPresentationModule.h +0 -13
  119. package/ios/EXNotifications/Notifications/Presenting/EXNotificationPresentationModule.m +0 -124
  120. package/ios/EXNotifications/Notifications/Scheduling/EXNotificationSchedulerModule.h +0 -21
  121. package/ios/EXNotifications/Notifications/Scheduling/EXNotificationSchedulerModule.m +0 -279
  122. package/ios/EXNotifications/PushToken/EXPushTokenListener.h +0 -14
  123. package/ios/EXNotifications/PushToken/EXPushTokenManager.h +0 -24
  124. package/ios/EXNotifications/PushToken/EXPushTokenManager.m +0 -63
  125. package/ios/EXNotifications/PushToken/EXPushTokenModule.h +0 -9
  126. package/ios/EXNotifications/PushToken/EXPushTokenModule.m +0 -154
package/CHANGELOG.md CHANGED
@@ -4,6 +4,90 @@
4
4
 
5
5
  ### 🛠 Breaking changes
6
6
 
7
+ - `DateTriggerInput` to only accept an object ([#33551](https://github.com/expo/expo/pull/33551) by [@vonovak](https://github.com/vonovak))
8
+
9
+ ### 🎉 New features
10
+
11
+ ### 🐛 Bug fixes
12
+
13
+ ### 💡 Others
14
+
15
+ ### ⚠️ Notices
16
+
17
+ - [iOS] Swift conversion 1: badge and server registration. ([#32069](https://github.com/expo/expo/pull/32069) by [@douglowder](https://github.com/douglowder))
18
+ - [iOS] Swift conversion 2: push token module. ([#32612](https://github.com/expo/expo/pull/32612) by [@douglowder](https://github.com/douglowder))
19
+ - [iOS] Swift conversion 3: scheduling, notification builder. ([#33253](https://github.com/expo/expo/pull/33253) by [@douglowder](https://github.com/douglowder))
20
+
21
+ ## 0.29.11 - 2024-12-05
22
+
23
+ ### 🐛 Bug fixes
24
+
25
+ - [android] fix data serialization for notifications with `ChannelAwareTrigger` ([#33354](https://github.com/expo/expo/pull/33354) by [@alextoudic](https://github.com/alextoudic))
26
+ - Add additional fallback value for project ID in `getExpoPushTokenAsync` ([#33359](https://github.com/expo/expo/pull/33359) by [@bradjones1](https://github.com/bradjones1))
27
+
28
+ ## 0.29.10 - 2024-12-02
29
+
30
+ ### 🐛 Bug fixes
31
+
32
+ - [android] fix notifications with custom sounds treated as silent ([#33311](https://github.com/expo/expo/pull/33311) by [@pennersr](https://github.com/pennersr))
33
+
34
+ ## 0.29.9 - 2024-11-29
35
+
36
+ ### 🐛 Bug fixes
37
+
38
+ - fix event subscription type export names ([#33295](https://github.com/expo/expo/pull/33295) by [@vonovak](https://github.com/vonovak))
39
+
40
+ ## 0.29.8 — 2024-11-14
41
+
42
+ _This version does not introduce any user-facing changes._
43
+
44
+ ## 0.29.7 — 2024-11-13
45
+
46
+ _This version does not introduce any user-facing changes._
47
+
48
+ ## 0.29.6 — 2024-11-10
49
+
50
+ ### 🎉 New features
51
+
52
+ - [android] run notification tasks from killed state ([#32531](https://github.com/expo/expo/pull/32531) by [@vonovak](https://github.com/vonovak))
53
+ - add `enableBackgroundRemoteNotifications` option to config plugin ([#32716](https://github.com/expo/expo/pull/32716) by [@vonovak](https://github.com/vonovak))
54
+
55
+ ## 0.29.5 — 2024-11-07
56
+
57
+ ### 🛠 Breaking changes
58
+
59
+ - remove two deprecated exports ([#32660](https://github.com/expo/expo/pull/32660) by [@vonovak](https://github.com/vonovak))
60
+
61
+ ### 🐛 Bug fixes
62
+
63
+ - fix `NotificationTrigger` type ([#32659](https://github.com/expo/expo/pull/32659) by [@vonovak](https://github.com/vonovak))
64
+
65
+ ### 💡 Others
66
+
67
+ - [docs] minor improvements to TS docs ([#32658](https://github.com/expo/expo/pull/32658) by [@vonovak](https://github.com/vonovak))
68
+
69
+ ## 0.29.4 — 2024-10-29
70
+
71
+ _This version does not introduce any user-facing changes._
72
+
73
+ ## 0.29.3 — 2024-10-25
74
+
75
+ ### 💡 Others
76
+
77
+ - remove unused deps ([#32272](https://github.com/expo/expo/pull/32272) by [@vonovak](https://github.com/vonovak))
78
+
79
+ ## 0.29.2 — 2024-10-24
80
+
81
+ _This version does not introduce any user-facing changes._
82
+
83
+ ## 0.29.1 — 2024-10-24
84
+
85
+ _This version does not introduce any user-facing changes._
86
+
87
+ ## 0.29.0 — 2024-10-22
88
+
89
+ ### 🛠 Breaking changes
90
+
7
91
  - Bumped iOS deployment target to 15.1. ([#30840](https://github.com/expo/expo/pull/30840), [#30862](https://github.com/expo/expo/pull/30862) by [@tsapeta](https://github.com/tsapeta))
8
92
  - Simplify calendar trigger input types. ([#31598](https://github.com/expo/expo/pull/31598) by [@douglowder](https://github.com/douglowder))
9
93
 
@@ -14,6 +98,7 @@
14
98
 
15
99
  ### 🐛 Bug fixes
16
100
 
101
+ - [android] fix: allow data message to control notification appearance ([#32162](https://github.com/expo/expo/pull/32162) by [@vonovak](https://github.com/vonovak))
17
102
  - [ios] fix crash if expo-update reload happens while Notifications.requestPermissionsAsync() is showing native dialog ([#32096](https://github.com/expo/expo/pull/32096) by [@mfazekas](https://github.com/mfazekas))
18
103
  - [android] `createNotificationChannel` could return incorrect channel information ([#32000](https://github.com/expo/expo/pull/32000) by [@vonovak](https://github.com/vonovak))
19
104
  - [android] fix notifications with `ChannelAwareTrigger` not being presented ([#31999](https://github.com/expo/expo/pull/31999) by [@vonovak](https://github.com/vonovak))
@@ -25,6 +110,7 @@
25
110
 
26
111
  ### 💡 Others
27
112
 
113
+ - warn when using push tokens in Expo Go ([#32122](https://github.com/expo/expo/pull/32122) by [@vonovak](https://github.com/vonovak))
28
114
  - [android] refactor trigger serialization ([#32032](https://github.com/expo/expo/pull/32032) by [@vonovak](https://github.com/vonovak))
29
115
  - [android] simplify DateTrigger ([#32002](https://github.com/expo/expo/pull/32002) by [@vonovak](https://github.com/vonovak))
30
116
  - [android] refactor ExpoNotificationBuilder ([#31838](https://github.com/expo/expo/pull/31838) by [@vonovak](https://github.com/vonovak))
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-parcelize'
3
3
 
4
4
  group = 'host.exp.exponent'
5
- version = '0.28.3'
5
+ version = '0.29.8'
6
6
 
7
7
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
8
8
  apply from: expoModulesCorePlugin
@@ -15,7 +15,7 @@ android {
15
15
  namespace "expo.modules.notifications"
16
16
  defaultConfig {
17
17
  versionCode 21
18
- versionName '0.28.3'
18
+ versionName '0.29.8'
19
19
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20
20
  }
21
21
 
@@ -30,6 +30,7 @@ import expo.modules.notifications.notifications.model.NotificationResponse;
30
30
  import expo.modules.notifications.notifications.model.TextInputNotificationResponse;
31
31
  import expo.modules.notifications.notifications.model.triggers.FirebaseNotificationTrigger;
32
32
 
33
+ import expo.modules.notifications.notifications.triggers.ChannelAwareTrigger;
33
34
  import expo.modules.notifications.notifications.triggers.DailyTrigger;
34
35
  import expo.modules.notifications.notifications.triggers.DateTrigger;
35
36
  import expo.modules.notifications.notifications.triggers.MonthlyTrigger;
@@ -79,6 +80,7 @@ public class NotificationSerializer {
79
80
  }
80
81
  } else if(
81
82
  requestTrigger instanceof SchedulableNotificationTrigger ||
83
+ requestTrigger instanceof ChannelAwareTrigger ||
82
84
  requestTrigger == null
83
85
  ) {
84
86
  JSONObject body = request.getContent().getBody();
@@ -6,6 +6,7 @@ import com.google.firebase.messaging.RemoteMessage;
6
6
 
7
7
  import java.util.Map;
8
8
 
9
+ import androidx.annotation.NonNull;
9
10
  import androidx.annotation.Nullable;
10
11
 
11
12
  /**
@@ -19,7 +20,7 @@ public class RemoteMessageSerializer {
19
20
  * @param message {@link RemoteMessage} to serialize
20
21
  * @return Serialized message
21
22
  */
22
- public static Bundle toBundle(RemoteMessage message) {
23
+ public static @NonNull Bundle toBundle(RemoteMessage message) {
23
24
  Bundle serializedMessage = new Bundle();
24
25
  serializedMessage.putString("collapseKey", message.getCollapseKey());
25
26
  serializedMessage.putBundle("data", toBundle(message.getData()));
@@ -6,6 +6,7 @@ import android.content.Context;
6
6
  import android.os.Bundle;
7
7
  import android.os.PersistableBundle;
8
8
  import android.util.Log;
9
+ import androidx.annotation.NonNull;
9
10
 
10
11
  import org.json.JSONException;
11
12
  import org.json.JSONObject;
@@ -120,5 +121,9 @@ public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer imple
120
121
  return bundle;
121
122
  }
122
123
 
124
+ public void executeTask(@NonNull Bundle bundle) {
125
+ mTask.execute(bundle, null);
126
+ }
127
+
123
128
  //endregion
124
129
  }
@@ -22,6 +22,7 @@ import java.io.Serializable;
22
22
  import androidx.annotation.NonNull;
23
23
  import androidx.annotation.Nullable;
24
24
 
25
+ import androidx.annotation.VisibleForTesting;
25
26
  import expo.modules.notifications.notifications.enums.NotificationPriority;
26
27
  import expo.modules.notifications.notifications.interfaces.INotificationContent;
27
28
  import kotlin.coroutines.Continuation;
@@ -320,6 +321,15 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
320
321
  return this;
321
322
  }
322
323
 
324
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
325
+ Builder disableVibrations() {
326
+ // remote notifications can come without vibrations
327
+ // we use this method do emulate that in tests
328
+ content.mShouldUseDefaultVibrationPattern = false;
329
+ content.mVibrationPattern = null;
330
+ return this;
331
+ }
332
+
323
333
  public Builder setVibrationPattern(long[] vibrationPattern) {
324
334
  content.mShouldUseDefaultVibrationPattern = false;
325
335
  content.mVibrationPattern = vibrationPattern;
@@ -0,0 +1,69 @@
1
+ package expo.modules.notifications.notifications.model
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ /*
7
+ * In some scenarios, data-only push notifications are, in fact, presented.
8
+ * The presentation preferences are taken from the data payload.
9
+ *
10
+ * https://docs.expo.dev/versions/latest/sdk/notifications/#android-push-notification-payload-specification
11
+ * */
12
+ @JvmInline
13
+ value class NotificationData(private val data: Map<String, String>) {
14
+ val title: String?
15
+ get() = data["title"]
16
+
17
+ val message: String?
18
+ get() = data["message"]
19
+
20
+ val body: JSONObject?
21
+ get() = try {
22
+ data["body"]?.let { JSONObject(it) }
23
+ } catch (e: Exception) {
24
+ null
25
+ }
26
+
27
+ val sound: String?
28
+ get() = data["sound"]
29
+
30
+ val shouldPlayDefaultSound: Boolean
31
+ get() = sound == null
32
+
33
+ val shouldUseDefaultVibrationPattern: Boolean
34
+ get() = data["vibrate"]?.toBoolean() == true
35
+
36
+ val isSticky: Boolean
37
+ get() = data["sticky"]?.toBoolean() ?: false
38
+
39
+ val vibrationPattern: LongArray?
40
+ get() = try {
41
+ data["vibrate"]?.let { vibrateString ->
42
+ JSONArray(vibrateString).let { jsonArray ->
43
+ LongArray(jsonArray.length()) { i ->
44
+ jsonArray.getLong(i)
45
+ }
46
+ }
47
+ }
48
+ } catch (e: Exception) {
49
+ // most likely a boolean value that cannot be converted to a longArray
50
+ null
51
+ }
52
+
53
+ val color: String? get() = data["color"]
54
+
55
+ val autoDismiss: Boolean
56
+ get() = data["autoDismiss"]?.toBoolean() ?: true
57
+
58
+ val categoryId: String?
59
+ get() = data["categoryId"]
60
+
61
+ val sticky: Boolean
62
+ get() = data["sticky"]?.toBoolean() ?: false
63
+
64
+ val subText: String?
65
+ get() = data["subtitle"]
66
+
67
+ val badge: Int?
68
+ get() = data["badge"]?.toIntOrNull()
69
+ }
@@ -8,7 +8,6 @@ import com.google.firebase.messaging.RemoteMessage
8
8
  import expo.modules.notifications.notifications.enums.NotificationPriority
9
9
  import expo.modules.notifications.notifications.interfaces.INotificationContent
10
10
  import expo.modules.notifications.notifications.presentation.builders.downloadImage
11
- import org.json.JSONObject
12
11
 
13
12
  /**
14
13
  * A POJO representing a remote notification content: title, message, body, etc.
@@ -21,6 +20,8 @@ class RemoteNotificationContent(private val remoteMessage: RemoteMessage) : INot
21
20
 
22
21
  constructor(parcel: Parcel) : this(parcel.readParcelable<RemoteMessage>(RemoteMessage::class.java.classLoader)!!)
23
22
 
23
+ private val notificationData = NotificationData(remoteMessage.data)
24
+
24
25
  override suspend fun getImage(context: Context): Bitmap? {
25
26
  val uri = remoteMessage.notification?.imageUrl
26
27
  return uri?.let { downloadImage(it) }
@@ -30,30 +31,20 @@ class RemoteNotificationContent(private val remoteMessage: RemoteMessage) : INot
30
31
  return remoteMessage.notification?.imageUrl != null
31
32
  }
32
33
 
33
- override val title: String?
34
- get() = remoteMessage.notification?.title
34
+ override val title = remoteMessage.notification?.title ?: notificationData.title
35
35
 
36
- override val text: String?
37
- get() = remoteMessage.notification?.body
36
+ override val text = remoteMessage.notification?.body ?: notificationData.message
38
37
 
39
- override val shouldPlayDefaultSound: Boolean
40
- get() = remoteMessage.notification?.sound == null
38
+ override val shouldPlayDefaultSound = remoteMessage.notification?.sound == null && notificationData.shouldPlayDefaultSound
41
39
 
42
- override val soundName: String?
43
- get() = remoteMessage.notification?.sound
40
+ override val soundName = remoteMessage.notification?.sound ?: notificationData.sound
44
41
 
45
42
  override val shouldUseDefaultVibrationPattern: Boolean
46
- get() = remoteMessage.notification?.defaultVibrateSettings == true
43
+ get() = remoteMessage.notification?.defaultVibrateSettings ?: notificationData.shouldUseDefaultVibrationPattern
47
44
 
48
- override val vibrationPattern: LongArray?
49
- get() = remoteMessage.notification?.vibrateTimings
45
+ override val vibrationPattern = remoteMessage.notification?.vibrateTimings ?: notificationData.vibrationPattern
50
46
 
51
- override val body: JSONObject?
52
- get() = try {
53
- remoteMessage.data["body"]?.let { JSONObject(it) }
54
- } catch (e: Exception) {
55
- null
56
- }
47
+ override val body = notificationData.body
57
48
 
58
49
  override val priority: NotificationPriority
59
50
  get() = when (remoteMessage.priority) {
@@ -62,24 +53,23 @@ class RemoteNotificationContent(private val remoteMessage: RemoteMessage) : INot
62
53
  }
63
54
 
64
55
  override val color: Number?
65
- get() = remoteMessage.notification?.color?.let { android.graphics.Color.parseColor(it) }
56
+ get() {
57
+ val colorSource = remoteMessage.notification?.color ?: notificationData.color
58
+ return colorSource?.let { android.graphics.Color.parseColor(it) }
59
+ }
66
60
 
67
61
  // NOTE the following getter functions are here because the local notification content class has them
68
- // and this class conforms to the same interface. They are not supported by FCM.
69
- override val isAutoDismiss: Boolean
70
- get() = remoteMessage.data["autoDismiss"]?.toBoolean() ?: true
62
+ // and this class conforms to the same interface.
63
+ // They are not supported by FCM but were previously implemented by JSONNotificationContentBuilder.java.
64
+ override val isAutoDismiss = notificationData.autoDismiss
71
65
 
72
- override val categoryId: String?
73
- get() = remoteMessage.data["categoryId"]
66
+ override val categoryId = notificationData.categoryId
74
67
 
75
- override val isSticky: Boolean
76
- get() = remoteMessage.data["sticky"]?.toBoolean() ?: false
68
+ override val isSticky = notificationData.isSticky
77
69
 
78
- override val subText: String?
79
- get() = remoteMessage.data["subtitle"]
70
+ override val subText = notificationData.subText
80
71
 
81
- override val badgeCount: Number?
82
- get() = remoteMessage.data["badge"]?.toIntOrNull()
72
+ override val badgeCount = notificationData.badge
83
73
 
84
74
  override fun describeContents(): Int = 0
85
75
 
@@ -5,6 +5,7 @@ import android.content.Context
5
5
  import android.content.pm.PackageManager
6
6
  import android.graphics.Bitmap
7
7
  import android.graphics.BitmapFactory
8
+ import android.os.Build
8
9
  import android.os.Bundle
9
10
  import android.os.Parcel
10
11
  import android.provider.Settings
@@ -13,6 +14,7 @@ import androidx.core.app.NotificationCompat
13
14
  import androidx.core.app.RemoteInput
14
15
  import expo.modules.notifications.notifications.SoundResolver
15
16
  import expo.modules.notifications.notifications.enums.NotificationPriority
17
+ import expo.modules.notifications.notifications.interfaces.INotificationContent
16
18
  import expo.modules.notifications.notifications.model.NotificationAction
17
19
  import expo.modules.notifications.notifications.model.NotificationCategory
18
20
  import expo.modules.notifications.notifications.model.NotificationRequest
@@ -110,31 +112,7 @@ open class ExpoNotificationBuilder(
110
112
  notificationContent.badgeCount?.toInt()?.let { builder.setNumber(it) }
111
113
  notificationContent.categoryId?.let { addActionsToBuilder(builder, it) }
112
114
 
113
- val shouldPlayDefaultSound = shouldPlaySound() && content.shouldPlayDefaultSound
114
- if (shouldPlayDefaultSound && shouldVibrate()) {
115
- builder.setDefaults(NotificationCompat.DEFAULT_ALL) // set sound, vibration and lights
116
- } else if (shouldVibrate()) {
117
- builder.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
118
- } else if (shouldPlayDefaultSound) {
119
- builder.setDefaults(NotificationCompat.DEFAULT_SOUND)
120
- } else {
121
- // Notification will not vibrate or play sound, regardless of channel
122
- builder.setSilent(true)
123
- }
124
-
125
- if (shouldPlaySound() && content.soundName != null) {
126
- content.soundName?.let { soundName ->
127
- val soundUri = SoundResolver(context).resolve(soundName)
128
- builder.setSound(soundUri)
129
- }
130
- } else if (shouldPlayDefaultSound) {
131
- builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
132
- }
133
-
134
- val vibrationPatternOverride = content.vibrationPattern
135
- if (shouldVibrate() && vibrationPatternOverride != null) {
136
- builder.setVibrate(vibrationPatternOverride)
137
- }
115
+ applySoundsAndVibrations(content, builder)
138
116
 
139
117
  if (content.body != null) {
140
118
  // Add body - JSON data - to extras
@@ -178,6 +156,42 @@ open class ExpoNotificationBuilder(
178
156
  return builder.build()
179
157
  }
180
158
 
159
+ private fun applySoundsAndVibrations(content: INotificationContent, builder: NotificationCompat.Builder) {
160
+ val shouldPlaySound = shouldPlaySound()
161
+ val shouldVibrate = shouldVibrate()
162
+
163
+ if (!shouldPlaySound && !shouldVibrate) {
164
+ // Notification will not vibrate or play sound, regardless of channel
165
+ builder.setSilent(true)
166
+ }
167
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
168
+ // the calls below are ignored on Android O and newer because the sound and vibration are set in the channel
169
+ val shouldPlayDefaultSound = shouldPlaySound && content.shouldPlayDefaultSound
170
+ val shouldUseDefaultVibrationPattern = shouldVibrate && content.shouldUseDefaultVibrationPattern
171
+ if (shouldUseDefaultVibrationPattern && shouldPlayDefaultSound) {
172
+ builder.setDefaults(NotificationCompat.DEFAULT_ALL)
173
+ } else {
174
+ if (shouldPlaySound) {
175
+ if (content.soundName != null) {
176
+ val soundUri = SoundResolver(context).resolve(content.soundName)
177
+ builder.setSound(soundUri)
178
+ } else if (shouldPlayDefaultSound) {
179
+ builder.setDefaults(NotificationCompat.DEFAULT_SOUND)
180
+ builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
181
+ }
182
+ }
183
+ if (shouldVibrate) {
184
+ val vibrationPatternOverride = content.vibrationPattern
185
+ if (vibrationPatternOverride != null) {
186
+ builder.setVibrate(vibrationPatternOverride)
187
+ } else if (shouldUseDefaultVibrationPattern) {
188
+ builder.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+
181
195
  /**
182
196
  * Marshalls [NotificationRequest] into to a byte array.
183
197
  *
@@ -45,7 +45,7 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
45
45
  }
46
46
 
47
47
  sListenersReferences[listener] = WeakReference(listener)
48
- if (!sPendingNotificationResponses.isEmpty()) {
48
+ if (sPendingNotificationResponses.isNotEmpty()) {
49
49
  val responseIterator = sPendingNotificationResponses.iterator()
50
50
  while (responseIterator.hasNext()) {
51
51
  listener.onNotificationResponseReceived(responseIterator.next())
@@ -139,11 +139,11 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
139
139
  if (notificationResponse.action.opensAppToForeground()) {
140
140
  openAppToForeground(context, notificationResponse)
141
141
  }
142
-
143
- if (getListeners().isEmpty()) {
142
+ val listeners = getListeners()
143
+ if (listeners.isEmpty()) {
144
144
  sPendingNotificationResponses.add(notificationResponse)
145
145
  } else {
146
- getListeners().forEach {
146
+ listeners.forEach {
147
147
  it.onNotificationResponseReceived(notificationResponse)
148
148
  }
149
149
  }
@@ -2,6 +2,7 @@ package expo.modules.notifications.service.delegates
2
2
 
3
3
  import android.content.Context
4
4
  import com.google.firebase.messaging.RemoteMessage
5
+ import expo.modules.interfaces.taskManager.TaskServiceProviderHelper
5
6
  import expo.modules.notifications.notifications.RemoteMessageSerializer
6
7
  import expo.modules.notifications.notifications.background.BackgroundRemoteNotificationTaskConsumer
7
8
  import expo.modules.notifications.notifications.debug.DebugLogging
@@ -94,9 +95,16 @@ open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseM
94
95
  val notification = createNotification(remoteMessage)
95
96
  DebugLogging.logNotification("FirebaseMessagingDelegate.onMessageReceived: notification", notification)
96
97
  NotificationsService.receive(context, notification)
97
- // background tasks are separate from the main notification handling flow; they are executed through task-manager
98
+ runTaskManagerTasks(remoteMessage)
99
+ }
100
+
101
+ private fun runTaskManagerTasks(remoteMessage: RemoteMessage) {
102
+ // getTaskServiceImpl() has a side effect:
103
+ // the TaskService constructor calls restoreTasks which then constructs a BackgroundRemoteNotificationTaskConsumer,
104
+ // and the getBackgroundTasks() call below doesn't return an empty collection.
105
+ TaskServiceProviderHelper.getTaskServiceImpl(context.applicationContext)
98
106
  getBackgroundTasks().forEach {
99
- it.scheduleJob(RemoteMessageSerializer.toBundle(remoteMessage))
107
+ it.executeTask(RemoteMessageSerializer.toBundle(remoteMessage))
100
108
  }
101
109
  }
102
110
 
@@ -6,6 +6,8 @@ export type DevicePushTokenRegistration = {
6
6
  isEnabled: boolean;
7
7
  };
8
8
  /**
9
+ * @hidden - the comment is misleading and the purpose of the function needs to be reevaluated
10
+ *
9
11
  * Sets the registration information so that the device push token gets pushed
10
12
  * to the given registration endpoint
11
13
  * @param enabled
@@ -1 +1 @@
1
- {"version":3,"file":"DevicePushTokenAutoRegistration.fx.d.ts","sourceRoot":"","sources":["../src/DevicePushTokenAutoRegistration.fx.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AAiBnC;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,qCAAqC,CAAC,OAAO,EAAE,OAAO,iBAY3E;AAGD,wBAAsB,sCAAsC,CAC1D,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,iBAiC5C"}
1
+ {"version":3,"file":"DevicePushTokenAutoRegistration.fx.d.ts","sourceRoot":"","sources":["../src/DevicePushTokenAutoRegistration.fx.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AAiBnC;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,qCAAqC,CAAC,OAAO,EAAE,OAAO,iBAY3E;AAGD,wBAAsB,sCAAsC,CAC1D,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,iBAiC5C"}
@@ -12,6 +12,8 @@ async function updatePushTokenAsync(token) {
12
12
  return await updateDevicePushTokenAsyncWithSignal(lastAbortController.signal, token);
13
13
  }
14
14
  /**
15
+ * @hidden - the comment is misleading and the purpose of the function needs to be reevaluated
16
+ *
15
17
  * Sets the registration information so that the device push token gets pushed
16
18
  * to the given registration endpoint
17
19
  * @param enabled
@@ -1 +1 @@
1
- {"version":3,"file":"DevicePushTokenAutoRegistration.fx.js","sourceRoot":"","sources":["../src/DevicePushTokenAutoRegistration.fx.ts"],"names":[],"mappings":"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","sourcesContent":["import 'abort-controller/polyfill';\nimport { UnavailabilityError } from 'expo-modules-core';\n\nimport ServerRegistrationModule from './ServerRegistrationModule';\nimport { addPushTokenListener } from './TokenEmitter';\nimport { DevicePushToken } from './Tokens.types';\nimport getDevicePushTokenAsync from './getDevicePushTokenAsync';\nimport { updateDevicePushTokenAsync as updateDevicePushTokenAsyncWithSignal } from './utils/updateDevicePushTokenAsync';\n\nlet lastAbortController: AbortController | null = null;\nasync function updatePushTokenAsync(token: DevicePushToken) {\n // Abort current update process\n lastAbortController?.abort();\n lastAbortController = new AbortController();\n return await updateDevicePushTokenAsyncWithSignal(lastAbortController.signal, token);\n}\n\n/**\n * Encapsulates device server registration data\n */\nexport type DevicePushTokenRegistration = {\n isEnabled: boolean;\n};\n\n/**\n * Sets the registration information so that the device push token gets pushed\n * to the given registration endpoint\n * @param enabled\n */\nexport async function setAutoServerRegistrationEnabledAsync(enabled: boolean) {\n // We are overwriting registration, so we shouldn't let\n // any pending request complete.\n lastAbortController?.abort();\n\n if (!ServerRegistrationModule.setRegistrationInfoAsync) {\n throw new UnavailabilityError('ServerRegistrationModule', 'setRegistrationInfoAsync');\n }\n\n await ServerRegistrationModule.setRegistrationInfoAsync(\n enabled ? JSON.stringify({ isEnabled: enabled }) : null\n );\n}\n\n// note(Chmiela): This function is exported only for testing purposes.\nexport async function __handlePersistedRegistrationInfoAsync(\n registrationInfo: string | null | undefined\n) {\n if (!registrationInfo) {\n // No registration info, nothing to do\n return;\n }\n\n let registration: DevicePushTokenRegistration | null = null;\n try {\n registration = JSON.parse(registrationInfo);\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while fetching registration information for auto token updates.',\n e\n );\n }\n\n if (!registration?.isEnabled) {\n // Registration is invalid or not enabled, nothing more to do\n return;\n }\n\n try {\n // Since the registration is enabled, fetching a \"new\" device token\n // shouldn't be a problem.\n const latestDevicePushToken = await getDevicePushTokenAsync();\n await updatePushTokenAsync(latestDevicePushToken);\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while updating server registration with latest device push token.',\n e\n );\n }\n}\n\nif (ServerRegistrationModule.getRegistrationInfoAsync) {\n // A global scope (to get all the updates) device push token\n // subscription, never cleared.\n addPushTokenListener(async (token) => {\n try {\n // Before updating the push token on server we always check if we should\n // Since modules can't change their method availability while running, we\n // can assert it's defined.\n const registrationInfo = await ServerRegistrationModule.getRegistrationInfoAsync!();\n\n if (!registrationInfo) {\n // Registration is not enabled\n return;\n }\n\n const registration: DevicePushTokenRegistration | null = JSON.parse(registrationInfo);\n if (registration?.isEnabled) {\n // Dispatch an abortable task to update\n // registration with new token.\n await updatePushTokenAsync(token);\n }\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while updating server registration with latest device push token.',\n e\n );\n }\n });\n\n // Verify if persisted registration\n // has successfully uploaded last known\n // device push token. If not, retry.\n ServerRegistrationModule.getRegistrationInfoAsync().then(__handlePersistedRegistrationInfoAsync);\n} else {\n console.warn(\n `[expo-notifications] Error encountered while fetching auto-registration state, new tokens will not be automatically registered on server.`,\n new UnavailabilityError('ServerRegistrationModule', 'getRegistrationInfoAsync')\n );\n}\n"]}
1
+ {"version":3,"file":"DevicePushTokenAutoRegistration.fx.js","sourceRoot":"","sources":["../src/DevicePushTokenAutoRegistration.fx.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,uBAAuB,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,0BAA0B,IAAI,oCAAoC,EAAE,MAAM,oCAAoC,CAAC;AAExH,IAAI,mBAAmB,GAA2B,IAAI,CAAC;AACvD,KAAK,UAAU,oBAAoB,CAAC,KAAsB;IACxD,+BAA+B;IAC/B,mBAAmB,EAAE,KAAK,EAAE,CAAC;IAC7B,mBAAmB,GAAG,IAAI,eAAe,EAAE,CAAC;IAC5C,OAAO,MAAM,oCAAoC,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACvF,CAAC;AASD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CAAC,OAAgB;IAC1E,uDAAuD;IACvD,gCAAgC;IAChC,mBAAmB,EAAE,KAAK,EAAE,CAAC;IAE7B,IAAI,CAAC,wBAAwB,CAAC,wBAAwB,EAAE;QACtD,MAAM,IAAI,mBAAmB,CAAC,0BAA0B,EAAE,0BAA0B,CAAC,CAAC;KACvF;IAED,MAAM,wBAAwB,CAAC,wBAAwB,CACrD,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CACxD,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,sCAAsC,CAC1D,gBAA2C;IAE3C,IAAI,CAAC,gBAAgB,EAAE;QACrB,sCAAsC;QACtC,OAAO;KACR;IAED,IAAI,YAAY,GAAuC,IAAI,CAAC;IAC5D,IAAI;QACF,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;KAC7C;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,IAAI,CACV,wGAAwG,EACxG,CAAC,CACF,CAAC;KACH;IAED,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE;QAC5B,6DAA6D;QAC7D,OAAO;KACR;IAED,IAAI;QACF,mEAAmE;QACnE,0BAA0B;QAC1B,MAAM,qBAAqB,GAAG,MAAM,uBAAuB,EAAE,CAAC;QAC9D,MAAM,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;KACnD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,IAAI,CACV,0GAA0G,EAC1G,CAAC,CACF,CAAC;KACH;AACH,CAAC;AAED,IAAI,wBAAwB,CAAC,wBAAwB,EAAE;IACrD,4DAA4D;IAC5D,+BAA+B;IAC/B,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACnC,IAAI;YACF,wEAAwE;YACxE,yEAAyE;YACzE,2BAA2B;YAC3B,MAAM,gBAAgB,GAAG,MAAM,wBAAwB,CAAC,wBAAyB,EAAE,CAAC;YAEpF,IAAI,CAAC,gBAAgB,EAAE;gBACrB,8BAA8B;gBAC9B,OAAO;aACR;YAED,MAAM,YAAY,GAAuC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACtF,IAAI,YAAY,EAAE,SAAS,EAAE;gBAC3B,uCAAuC;gBACvC,+BAA+B;gBAC/B,MAAM,oBAAoB,CAAC,KAAK,CAAC,CAAC;aACnC;SACF;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CACV,0GAA0G,EAC1G,CAAC,CACF,CAAC;SACH;IACH,CAAC,CAAC,CAAC;IAEH,mCAAmC;IACnC,uCAAuC;IACvC,oCAAoC;IACpC,wBAAwB,CAAC,wBAAwB,EAAE,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;CAClG;KAAM;IACL,OAAO,CAAC,IAAI,CACV,2IAA2I,EAC3I,IAAI,mBAAmB,CAAC,0BAA0B,EAAE,0BAA0B,CAAC,CAChF,CAAC;CACH","sourcesContent":["import 'abort-controller/polyfill';\nimport { UnavailabilityError } from 'expo-modules-core';\n\nimport ServerRegistrationModule from './ServerRegistrationModule';\nimport { addPushTokenListener } from './TokenEmitter';\nimport { DevicePushToken } from './Tokens.types';\nimport getDevicePushTokenAsync from './getDevicePushTokenAsync';\nimport { updateDevicePushTokenAsync as updateDevicePushTokenAsyncWithSignal } from './utils/updateDevicePushTokenAsync';\n\nlet lastAbortController: AbortController | null = null;\nasync function updatePushTokenAsync(token: DevicePushToken) {\n // Abort current update process\n lastAbortController?.abort();\n lastAbortController = new AbortController();\n return await updateDevicePushTokenAsyncWithSignal(lastAbortController.signal, token);\n}\n\n/**\n * Encapsulates device server registration data\n */\nexport type DevicePushTokenRegistration = {\n isEnabled: boolean;\n};\n\n/**\n * @hidden - the comment is misleading and the purpose of the function needs to be reevaluated\n *\n * Sets the registration information so that the device push token gets pushed\n * to the given registration endpoint\n * @param enabled\n */\nexport async function setAutoServerRegistrationEnabledAsync(enabled: boolean) {\n // We are overwriting registration, so we shouldn't let\n // any pending request complete.\n lastAbortController?.abort();\n\n if (!ServerRegistrationModule.setRegistrationInfoAsync) {\n throw new UnavailabilityError('ServerRegistrationModule', 'setRegistrationInfoAsync');\n }\n\n await ServerRegistrationModule.setRegistrationInfoAsync(\n enabled ? JSON.stringify({ isEnabled: enabled }) : null\n );\n}\n\n// note(Chmiela): This function is exported only for testing purposes.\nexport async function __handlePersistedRegistrationInfoAsync(\n registrationInfo: string | null | undefined\n) {\n if (!registrationInfo) {\n // No registration info, nothing to do\n return;\n }\n\n let registration: DevicePushTokenRegistration | null = null;\n try {\n registration = JSON.parse(registrationInfo);\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while fetching registration information for auto token updates.',\n e\n );\n }\n\n if (!registration?.isEnabled) {\n // Registration is invalid or not enabled, nothing more to do\n return;\n }\n\n try {\n // Since the registration is enabled, fetching a \"new\" device token\n // shouldn't be a problem.\n const latestDevicePushToken = await getDevicePushTokenAsync();\n await updatePushTokenAsync(latestDevicePushToken);\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while updating server registration with latest device push token.',\n e\n );\n }\n}\n\nif (ServerRegistrationModule.getRegistrationInfoAsync) {\n // A global scope (to get all the updates) device push token\n // subscription, never cleared.\n addPushTokenListener(async (token) => {\n try {\n // Before updating the push token on server we always check if we should\n // Since modules can't change their method availability while running, we\n // can assert it's defined.\n const registrationInfo = await ServerRegistrationModule.getRegistrationInfoAsync!();\n\n if (!registrationInfo) {\n // Registration is not enabled\n return;\n }\n\n const registration: DevicePushTokenRegistration | null = JSON.parse(registrationInfo);\n if (registration?.isEnabled) {\n // Dispatch an abortable task to update\n // registration with new token.\n await updatePushTokenAsync(token);\n }\n } catch (e) {\n console.warn(\n '[expo-notifications] Error encountered while updating server registration with latest device push token.',\n e\n );\n }\n });\n\n // Verify if persisted registration\n // has successfully uploaded last known\n // device push token. If not, retry.\n ServerRegistrationModule.getRegistrationInfoAsync().then(__handlePersistedRegistrationInfoAsync);\n} else {\n console.warn(\n `[expo-notifications] Error encountered while fetching auto-registration state, new tokens will not be automatically registered on server.`,\n new UnavailabilityError('ServerRegistrationModule', 'getRegistrationInfoAsync')\n );\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { ProxyNativeModule } from 'expo-modules-core';
2
2
  import { NotificationChannel } from './NotificationChannelManager.types';
3
3
  /**
4
- * An object represents a notification channel group.
4
+ * An object which represents a notification channel group.
5
5
  * @platform android
6
6
  */
7
7
  export interface NotificationChannelGroup {
@@ -12,7 +12,7 @@ export interface NotificationChannelGroup {
12
12
  channels: NotificationChannel[];
13
13
  }
14
14
  /**
15
- * An object represents a notification channel group to be set.
15
+ * An object which represents a notification channel group to be set.
16
16
  * @platform android
17
17
  */
18
18
  export interface NotificationChannelGroupInput {
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationChannelGroupManager.types.js","sourceRoot":"","sources":["../src/NotificationChannelGroupManager.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ProxyNativeModule } from 'expo-modules-core';\n\nimport { NotificationChannel } from './NotificationChannelManager.types';\n\n/**\n * An object represents a notification channel group.\n * @platform android\n */\nexport interface NotificationChannelGroup {\n id: string;\n name: string | null;\n description?: string | null;\n isBlocked?: boolean;\n channels: NotificationChannel[];\n}\n\n/**\n * An object represents a notification channel group to be set.\n * @platform android\n */\nexport interface NotificationChannelGroupInput {\n name: string | null;\n description?: string | null;\n}\n\nexport interface NotificationChannelGroupManager extends ProxyNativeModule {\n getNotificationChannelGroupsAsync?: () => Promise<NotificationChannelGroup[]>;\n getNotificationChannelGroupAsync?: (groupId: string) => Promise<NotificationChannelGroup | null>;\n setNotificationChannelGroupAsync?: (\n groupId: string,\n group: NotificationChannelGroupInput\n ) => Promise<NotificationChannelGroup | null>;\n deleteNotificationChannelGroupAsync?: (groupId: string) => Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"NotificationChannelGroupManager.types.js","sourceRoot":"","sources":["../src/NotificationChannelGroupManager.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ProxyNativeModule } from 'expo-modules-core';\n\nimport { NotificationChannel } from './NotificationChannelManager.types';\n\n/**\n * An object which represents a notification channel group.\n * @platform android\n */\nexport interface NotificationChannelGroup {\n id: string;\n name: string | null;\n description?: string | null;\n isBlocked?: boolean;\n channels: NotificationChannel[];\n}\n\n/**\n * An object which represents a notification channel group to be set.\n * @platform android\n */\nexport interface NotificationChannelGroupInput {\n name: string | null;\n description?: string | null;\n}\n\nexport interface NotificationChannelGroupManager extends ProxyNativeModule {\n getNotificationChannelGroupsAsync?: () => Promise<NotificationChannelGroup[]>;\n getNotificationChannelGroupAsync?: (groupId: string) => Promise<NotificationChannelGroup | null>;\n setNotificationChannelGroupAsync?: (\n groupId: string,\n group: NotificationChannelGroupInput\n ) => Promise<NotificationChannelGroup | null>;\n deleteNotificationChannelGroupAsync?: (groupId: string) => Promise<void>;\n}\n"]}
@@ -19,10 +19,6 @@ export declare enum AndroidImportance {
19
19
  MIN = 3,
20
20
  LOW = 4,
21
21
  DEFAULT = 5,
22
- /**
23
- * @deprecated Use `DEFAULT` instead.
24
- */
25
- DEEFAULT = 5,
26
22
  HIGH = 6,
27
23
  MAX = 7
28
24
  }
@@ -53,7 +49,7 @@ export interface AudioAttributes {
53
49
  }
54
50
  export type AudioAttributesInput = Partial<AudioAttributes>;
55
51
  /**
56
- * An object represents a notification channel.
52
+ * An object which represents a notification channel.
57
53
  * @platform android
58
54
  */
59
55
  export interface NotificationChannel {
@@ -74,7 +70,7 @@ export interface NotificationChannel {
74
70
  }
75
71
  export type RequiredBy<T, K extends keyof T> = Partial<Omit<T, K>> & Required<Pick<T, K>>;
76
72
  /**
77
- * An object represents a notification channel to be set.
73
+ * An object which represents a notification channel to be set.
78
74
  * @platform android
79
75
  */
80
76
  export type NotificationChannelInput = RequiredBy<Omit<NotificationChannel, 'id' | 'audioAttributes' | 'sound'> & {
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationChannelManager.types.d.ts","sourceRoot":"","sources":["../src/NotificationChannelManager.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NotificationChannelManager.types.d.ts","sourceRoot":"","sources":["../src/NotificationChannelManager.types.ts"],"names":[],"mappings":"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"}
@@ -24,10 +24,6 @@ export var AndroidImportance;
24
24
  AndroidImportance[AndroidImportance["MIN"] = 3] = "MIN";
25
25
  AndroidImportance[AndroidImportance["LOW"] = 4] = "LOW";
26
26
  AndroidImportance[AndroidImportance["DEFAULT"] = 5] = "DEFAULT";
27
- /**
28
- * @deprecated Use `DEFAULT` instead.
29
- */
30
- AndroidImportance[AndroidImportance["DEEFAULT"] = 5] = "DEEFAULT";
31
27
  AndroidImportance[AndroidImportance["HIGH"] = 6] = "HIGH";
32
28
  AndroidImportance[AndroidImportance["MAX"] = 7] = "MAX";
33
29
  })(AndroidImportance || (AndroidImportance = {}));