expo-notifications 0.28.17 → 0.28.18

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/CHANGELOG.md CHANGED
@@ -10,6 +10,16 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.28.18 — 2024-10-01
14
+
15
+ ### 🎉 New features
16
+
17
+ - Add clearLastNotificationResponseAsync to API. ([#31607](https://github.com/expo/expo/pull/31607) by [@douglowder](https://github.com/douglowder))
18
+
19
+ ### 🐛 Bug fixes
20
+
21
+ - [android] fix notifications actions not being presented ([#31795](https://github.com/expo/expo/pull/31795) by [@vonovak](https://github.com/vonovak))
22
+
13
23
  ## 0.28.17 — 2024-09-17
14
24
 
15
25
  ### 🐛 Bug fixes
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'host.exp.exponent'
4
- version = '0.28.17'
4
+ version = '0.28.18'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,7 +14,7 @@ android {
14
14
  namespace "expo.modules.notifications"
15
15
  defaultConfig {
16
16
  versionCode 21
17
- versionName '0.28.17'
17
+ versionName '0.28.18'
18
18
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19
19
  }
20
20
 
@@ -41,6 +41,11 @@ open class NotificationsEmitter : Module(), NotificationListener {
41
41
  AsyncFunction<Bundle?>("getLastNotificationResponseAsync") {
42
42
  lastNotificationResponseBundle
43
43
  }
44
+
45
+ AsyncFunction("clearLastNotificationResponseAsync") {
46
+ lastNotificationResponseBundle = null
47
+ null
48
+ }
44
49
  }
45
50
 
46
51
  /**
@@ -24,7 +24,7 @@ import kotlin.math.min
24
24
  */
25
25
  open class ExpoNotificationBuilder(context: Context?) : ChannelAwareNotificationBuilder(context) {
26
26
  override suspend fun build(): Notification {
27
- val builder = super.createBuilder()
27
+ val builder = createBuilder()
28
28
  builder.setSmallIcon(icon)
29
29
  builder.setPriority(priority)
30
30
 
@@ -69,7 +69,17 @@ export declare function addNotificationResponseReceivedListener(listener: (event
69
69
  */
70
70
  export declare function removeNotificationSubscription(subscription: Subscription): void;
71
71
  /**
72
- * @header listen
72
+ * Gets the notification response that was received most recently
73
+ * (a notification response designates an interaction with a notification, such as tapping on it).
74
+ *
75
+ * - `null` - if no notification response has been received yet
76
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received
77
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.
73
78
  */
74
79
  export declare function getLastNotificationResponseAsync(): Promise<NotificationResponse | null>;
80
+ export declare function clearLastNotificationResponseAsync(): Promise<void>;
81
+ /**
82
+ * @hidden
83
+ */
84
+ export declare function addNotificationResponseClearedListener(listener: () => void): Subscription;
75
85
  //# sourceMappingURL=NotificationsEmitter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsEmitter.d.ts","sourceRoot":"","sources":["../src/NotificationsEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEpF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAY3E,eAAO,MAAM,yBAAyB,+CAA+C,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GACtC,YAAY,CAQd;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,YAAY,CAElF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAC9C,YAAY,CAQd;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,YAAY,QAExE;AAGD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAO7F"}
1
+ {"version":3,"file":"NotificationsEmitter.d.ts","sourceRoot":"","sources":["../src/NotificationsEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEpF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAa3E,eAAO,MAAM,yBAAyB,+CAA+C,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GACtC,YAAY,CAQd;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,YAAY,CAElF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAC9C,YAAY,CAQd;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,YAAY,QAExE;AAED;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAO7F;AAYD,wBAAsB,kCAAkC,IAAI,OAAO,CAAC,IAAI,CAAC,CAOxE;AAED;;GAEG;AACH,wBAAgB,sCAAsC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,YAAY,CAEzF"}
@@ -6,6 +6,7 @@ const emitter = new EventEmitter(NotificationsEmitterModule);
6
6
  const didReceiveNotificationEventName = 'onDidReceiveNotification';
7
7
  const didDropNotificationsEventName = 'onNotificationsDeleted';
8
8
  const didReceiveNotificationResponseEventName = 'onDidReceiveNotificationResponse';
9
+ const didClearNotificationResponseEventName = 'onDidClearNotificationResponse';
9
10
  // @docsMissing
10
11
  export const DEFAULT_ACTION_IDENTIFIER = 'expo.modules.notifications.actions.DEFAULT';
11
12
  /**
@@ -89,9 +90,13 @@ export function addNotificationResponseReceivedListener(listener) {
89
90
  export function removeNotificationSubscription(subscription) {
90
91
  emitter.removeSubscription(subscription);
91
92
  }
92
- // @docsMissing
93
93
  /**
94
- * @header listen
94
+ * Gets the notification response that was received most recently
95
+ * (a notification response designates an interaction with a notification, such as tapping on it).
96
+ *
97
+ * - `null` - if no notification response has been received yet
98
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received
99
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.
95
100
  */
96
101
  export async function getLastNotificationResponseAsync() {
97
102
  if (!NotificationsEmitterModule.getLastNotificationResponseAsync) {
@@ -101,4 +106,28 @@ export async function getLastNotificationResponseAsync() {
101
106
  const mappedResponse = response ? mapNotificationResponse(response) : response;
102
107
  return mappedResponse;
103
108
  }
109
+ /* Clears the notification response that was received most recently. May be used
110
+ * when an app selects a route based on the notification response, and it is undesirable
111
+ * to continue selecting the route after the response has already been handled.
112
+ * to continue to select the route after the response has already been handled.
113
+ *
114
+ * If a component is using the [`useLastNotificationResponse`](#useLastNotificationResponse) hook,
115
+ * this call will also clear the value returned by the hook.
116
+ *
117
+ * @return A promise that resolves if the native call was successful.
118
+ */
119
+ export async function clearLastNotificationResponseAsync() {
120
+ if (!NotificationsEmitterModule.clearLastNotificationResponseAsync) {
121
+ throw new UnavailabilityError('ExpoNotifications', 'getLastNotificationResponseAsync');
122
+ }
123
+ await NotificationsEmitterModule.clearLastNotificationResponseAsync();
124
+ // Emit event to clear any useLastNotificationResponse hooks, after native call succeeds
125
+ emitter.emit(didClearNotificationResponseEventName, []);
126
+ }
127
+ /**
128
+ * @hidden
129
+ */
130
+ export function addNotificationResponseClearedListener(listener) {
131
+ return emitter.addListener(didClearNotificationResponseEventName, listener);
132
+ }
104
133
  //# sourceMappingURL=NotificationsEmitter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsEmitter.js","sourceRoot":"","sources":["../src/NotificationsEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGpF,OAAO,0BAA0B,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE3F,iCAAiC;AACjC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,0BAA0B,CAAC,CAAC;AAE7D,MAAM,+BAA+B,GAAG,0BAA0B,CAAC;AACnE,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAC/D,MAAM,uCAAuC,GAAG,kCAAkC,CAAC;AAEnF,eAAe;AACf,MAAM,CAAC,MAAM,yBAAyB,GAAG,4CAA4C,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAAuC;IAEvC,OAAO,OAAO,CAAC,WAAW,CACxB,+BAA+B,EAC/B,CAAC,YAA0B,EAAE,EAAE;QAC7B,MAAM,kBAAkB,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;QACzD,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B,CAAC,QAAoB;IAClE,OAAO,OAAO,CAAC,WAAW,CAAO,6BAA6B,EAAE,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,uCAAuC,CACrD,QAA+C;IAE/C,OAAO,OAAO,CAAC,WAAW,CACxB,uCAAuC,EACvC,CAAC,QAA8B,EAAE,EAAE;QACjC,MAAM,cAAc,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACzD,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC3B,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,YAA0B;IACvE,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,eAAe;AACf;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,IAAI,CAAC,0BAA0B,CAAC,gCAAgC,EAAE;QAChE,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,kCAAkC,CAAC,CAAC;KACxF;IACD,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAAC,gCAAgC,EAAE,CAAC;IACrF,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/E,OAAO,cAAc,CAAC;AACxB,CAAC","sourcesContent":["import { EventEmitter, Subscription, UnavailabilityError } from 'expo-modules-core';\n\nimport { Notification, NotificationResponse } from './Notifications.types';\nimport NotificationsEmitterModule from './NotificationsEmitterModule';\nimport { mapNotification, mapNotificationResponse } from './utils/mapNotificationResponse';\n\n// Web uses SyntheticEventEmitter\nconst emitter = new EventEmitter(NotificationsEmitterModule);\n\nconst didReceiveNotificationEventName = 'onDidReceiveNotification';\nconst didDropNotificationsEventName = 'onNotificationsDeleted';\nconst didReceiveNotificationResponseEventName = 'onDidReceiveNotificationResponse';\n\n// @docsMissing\nexport const DEFAULT_ACTION_IDENTIFIER = 'expo.modules.notifications.actions.DEFAULT';\n\n/**\n * Listeners registered by this method will be called whenever a notification is received while the app is running.\n * @param listener A function accepting a notification ([`Notification`](#notification)) as an argument.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @example Registering a notification listener using a React hook:\n * ```jsx\n * import React from 'react';\n * import * as Notifications from 'expo-notifications';\n *\n * export default function App() {\n * React.useEffect(() => {\n * const subscription = Notifications.addNotificationReceivedListener(notification => {\n * console.log(notification);\n * });\n * return () => subscription.remove();\n * }, []);\n *\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport function addNotificationReceivedListener(\n listener: (event: Notification) => void\n): Subscription {\n return emitter.addListener<Notification>(\n didReceiveNotificationEventName,\n (notification: Notification) => {\n const mappedNotification = mapNotification(notification);\n listener(mappedNotification);\n }\n );\n}\n\n/**\n * Listeners registered by this method will be called whenever some notifications have been dropped by the server.\n * Applicable only to Firebase Cloud Messaging which we use as a notifications service on Android. It corresponds to `onDeletedMessages()` callback.\n * More information can be found in [Firebase docs](https://firebase.google.com/docs/cloud-messaging/android/receive#override-ondeletedmessages).\n * @param listener A callback function.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @header listen\n */\nexport function addNotificationsDroppedListener(listener: () => void): Subscription {\n return emitter.addListener<void>(didDropNotificationsEventName, listener);\n}\n\n/**\n * Listeners registered by this method will be called whenever a user interacts with a notification (for example, taps on it).\n * @param listener A function accepting notification response ([`NotificationResponse`](#notificationresponse)) as an argument.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @example Register a notification responder listener:\n * ```jsx\n * import React from 'react';\n * import { Linking } from 'react-native';\n * import * as Notifications from 'expo-notifications';\n *\n * export default function Container() {\n * React.useEffect(() => {\n * const subscription = Notifications.addNotificationResponseReceivedListener(response => {\n * const url = response.notification.request.content.data.url;\n * Linking.openURL(url);\n * });\n * return () => subscription.remove();\n * }, []);\n *\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport function addNotificationResponseReceivedListener(\n listener: (event: NotificationResponse) => void\n): Subscription {\n return emitter.addListener<NotificationResponse>(\n didReceiveNotificationResponseEventName,\n (response: NotificationResponse) => {\n const mappedResponse = mapNotificationResponse(response);\n listener(mappedResponse);\n }\n );\n}\n\n/**\n * Removes a notification subscription returned by an `addNotificationListener` call.\n * @param subscription A subscription returned by `addNotificationListener` method.\n * @header listen\n */\nexport function removeNotificationSubscription(subscription: Subscription) {\n emitter.removeSubscription(subscription);\n}\n\n// @docsMissing\n/**\n * @header listen\n */\nexport async function getLastNotificationResponseAsync(): Promise<NotificationResponse | null> {\n if (!NotificationsEmitterModule.getLastNotificationResponseAsync) {\n throw new UnavailabilityError('ExpoNotifications', 'getLastNotificationResponseAsync');\n }\n const response = await NotificationsEmitterModule.getLastNotificationResponseAsync();\n const mappedResponse = response ? mapNotificationResponse(response) : response;\n return mappedResponse;\n}\n"]}
1
+ {"version":3,"file":"NotificationsEmitter.js","sourceRoot":"","sources":["../src/NotificationsEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGpF,OAAO,0BAA0B,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE3F,iCAAiC;AACjC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,0BAA0B,CAAC,CAAC;AAE7D,MAAM,+BAA+B,GAAG,0BAA0B,CAAC;AACnE,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAC/D,MAAM,uCAAuC,GAAG,kCAAkC,CAAC;AACnF,MAAM,qCAAqC,GAAG,gCAAgC,CAAC;AAE/E,eAAe;AACf,MAAM,CAAC,MAAM,yBAAyB,GAAG,4CAA4C,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAAuC;IAEvC,OAAO,OAAO,CAAC,WAAW,CACxB,+BAA+B,EAC/B,CAAC,YAA0B,EAAE,EAAE;QAC7B,MAAM,kBAAkB,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;QACzD,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B,CAAC,QAAoB;IAClE,OAAO,OAAO,CAAC,WAAW,CAAO,6BAA6B,EAAE,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,uCAAuC,CACrD,QAA+C;IAE/C,OAAO,OAAO,CAAC,WAAW,CACxB,uCAAuC,EACvC,CAAC,QAA8B,EAAE,EAAE;QACjC,MAAM,cAAc,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACzD,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC3B,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,YAA0B;IACvE,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,IAAI,CAAC,0BAA0B,CAAC,gCAAgC,EAAE;QAChE,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,kCAAkC,CAAC,CAAC;KACxF;IACD,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAAC,gCAAgC,EAAE,CAAC;IACrF,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/E,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,kCAAkC;IACtD,IAAI,CAAC,0BAA0B,CAAC,kCAAkC,EAAE;QAClE,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,kCAAkC,CAAC,CAAC;KACxF;IACD,MAAM,0BAA0B,CAAC,kCAAkC,EAAE,CAAC;IACtE,wFAAwF;IACxF,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sCAAsC,CAAC,QAAoB;IACzE,OAAO,OAAO,CAAC,WAAW,CAAO,qCAAqC,EAAE,QAAQ,CAAC,CAAC;AACpF,CAAC","sourcesContent":["import { EventEmitter, Subscription, UnavailabilityError } from 'expo-modules-core';\n\nimport { Notification, NotificationResponse } from './Notifications.types';\nimport NotificationsEmitterModule from './NotificationsEmitterModule';\nimport { mapNotification, mapNotificationResponse } from './utils/mapNotificationResponse';\n\n// Web uses SyntheticEventEmitter\nconst emitter = new EventEmitter(NotificationsEmitterModule);\n\nconst didReceiveNotificationEventName = 'onDidReceiveNotification';\nconst didDropNotificationsEventName = 'onNotificationsDeleted';\nconst didReceiveNotificationResponseEventName = 'onDidReceiveNotificationResponse';\nconst didClearNotificationResponseEventName = 'onDidClearNotificationResponse';\n\n// @docsMissing\nexport const DEFAULT_ACTION_IDENTIFIER = 'expo.modules.notifications.actions.DEFAULT';\n\n/**\n * Listeners registered by this method will be called whenever a notification is received while the app is running.\n * @param listener A function accepting a notification ([`Notification`](#notification)) as an argument.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @example Registering a notification listener using a React hook:\n * ```jsx\n * import React from 'react';\n * import * as Notifications from 'expo-notifications';\n *\n * export default function App() {\n * React.useEffect(() => {\n * const subscription = Notifications.addNotificationReceivedListener(notification => {\n * console.log(notification);\n * });\n * return () => subscription.remove();\n * }, []);\n *\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport function addNotificationReceivedListener(\n listener: (event: Notification) => void\n): Subscription {\n return emitter.addListener<Notification>(\n didReceiveNotificationEventName,\n (notification: Notification) => {\n const mappedNotification = mapNotification(notification);\n listener(mappedNotification);\n }\n );\n}\n\n/**\n * Listeners registered by this method will be called whenever some notifications have been dropped by the server.\n * Applicable only to Firebase Cloud Messaging which we use as a notifications service on Android. It corresponds to `onDeletedMessages()` callback.\n * More information can be found in [Firebase docs](https://firebase.google.com/docs/cloud-messaging/android/receive#override-ondeletedmessages).\n * @param listener A callback function.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @header listen\n */\nexport function addNotificationsDroppedListener(listener: () => void): Subscription {\n return emitter.addListener<void>(didDropNotificationsEventName, listener);\n}\n\n/**\n * Listeners registered by this method will be called whenever a user interacts with a notification (for example, taps on it).\n * @param listener A function accepting notification response ([`NotificationResponse`](#notificationresponse)) as an argument.\n * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.\n * @example Register a notification responder listener:\n * ```jsx\n * import React from 'react';\n * import { Linking } from 'react-native';\n * import * as Notifications from 'expo-notifications';\n *\n * export default function Container() {\n * React.useEffect(() => {\n * const subscription = Notifications.addNotificationResponseReceivedListener(response => {\n * const url = response.notification.request.content.data.url;\n * Linking.openURL(url);\n * });\n * return () => subscription.remove();\n * }, []);\n *\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport function addNotificationResponseReceivedListener(\n listener: (event: NotificationResponse) => void\n): Subscription {\n return emitter.addListener<NotificationResponse>(\n didReceiveNotificationResponseEventName,\n (response: NotificationResponse) => {\n const mappedResponse = mapNotificationResponse(response);\n listener(mappedResponse);\n }\n );\n}\n\n/**\n * Removes a notification subscription returned by an `addNotificationListener` call.\n * @param subscription A subscription returned by `addNotificationListener` method.\n * @header listen\n */\nexport function removeNotificationSubscription(subscription: Subscription) {\n emitter.removeSubscription(subscription);\n}\n\n/**\n * Gets the notification response that was received most recently\n * (a notification response designates an interaction with a notification, such as tapping on it).\n *\n * - `null` - if no notification response has been received yet\n * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received\n * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.\n */\nexport async function getLastNotificationResponseAsync(): Promise<NotificationResponse | null> {\n if (!NotificationsEmitterModule.getLastNotificationResponseAsync) {\n throw new UnavailabilityError('ExpoNotifications', 'getLastNotificationResponseAsync');\n }\n const response = await NotificationsEmitterModule.getLastNotificationResponseAsync();\n const mappedResponse = response ? mapNotificationResponse(response) : response;\n return mappedResponse;\n}\n\n/* Clears the notification response that was received most recently. May be used\n * when an app selects a route based on the notification response, and it is undesirable\n * to continue selecting the route after the response has already been handled.\n * to continue to select the route after the response has already been handled.\n *\n * If a component is using the [`useLastNotificationResponse`](#useLastNotificationResponse) hook,\n * this call will also clear the value returned by the hook.\n *\n * @return A promise that resolves if the native call was successful.\n */\nexport async function clearLastNotificationResponseAsync(): Promise<void> {\n if (!NotificationsEmitterModule.clearLastNotificationResponseAsync) {\n throw new UnavailabilityError('ExpoNotifications', 'getLastNotificationResponseAsync');\n }\n await NotificationsEmitterModule.clearLastNotificationResponseAsync();\n // Emit event to clear any useLastNotificationResponse hooks, after native call succeeds\n emitter.emit(didClearNotificationResponseEventName, []);\n}\n\n/**\n * @hidden\n */\nexport function addNotificationResponseClearedListener(listener: () => void): Subscription {\n return emitter.addListener<void>(didClearNotificationResponseEventName, listener);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useLastNotificationResponse.d.ts","sourceRoot":"","sources":["../src/useLastNotificationResponse.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAM7D,KAAK,yBAAyB,GAAG,oBAAoB,GAAG,IAAI,GAAG,SAAS,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B,8BA0ClD"}
1
+ {"version":3,"file":"useLastNotificationResponse.d.ts","sourceRoot":"","sources":["../src/useLastNotificationResponse.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAO7D,KAAK,yBAAyB,GAAG,oBAAoB,GAAG,IAAI,GAAG,SAAS,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B,8BA8ClD"}
@@ -1,5 +1,5 @@
1
1
  import { useLayoutEffect, useState } from 'react';
2
- import { addNotificationResponseReceivedListener, getLastNotificationResponseAsync, } from './NotificationsEmitter';
2
+ import { addNotificationResponseReceivedListener, addNotificationResponseClearedListener, getLastNotificationResponseAsync, } from './NotificationsEmitter';
3
3
  /**
4
4
  * A React hook always returns the notification response that was received most recently
5
5
  * (a notification response designates an interaction with a notification, such as tapping on it).
@@ -61,8 +61,12 @@ export default function useLastNotificationResponse() {
61
61
  getLastNotificationResponseAsync?.().then((response) => setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response)));
62
62
  // Set up listener for responses that come in, and set the last response if needed
63
63
  const subscription = addNotificationResponseReceivedListener((response) => setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response)));
64
+ const clearResponseSubscription = addNotificationResponseClearedListener(() => {
65
+ setLastNotificationResponse(undefined);
66
+ });
64
67
  return () => {
65
68
  subscription.remove();
69
+ clearResponseSubscription.remove();
66
70
  };
67
71
  }, []);
68
72
  return lastNotificationResponse;
@@ -1 +1 @@
1
- {"version":3,"file":"useLastNotificationResponse.js","sourceRoot":"","sources":["../src/useLastNotificationResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EACL,uCAAuC,EACvC,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAIhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B;IACjD,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,GAC3D,QAAQ,CAA4B,SAAS,CAAC,CAAC;IAEjD,oFAAoF;IACpF,yCAAyC;IACzC,MAAM,mBAAmB,GAAG,CAC1B,YAAuC,EACvC,WAAsC,EACtC,EAAE;QACF,+DAA+D;QAC/D,IAAI,CAAC,WAAW,EAAE;YAChB,OAAO,YAAY,CAAC;SACrB;QACD,8FAA8F;QAC9F,IAAI,CAAC,YAAY,EAAE;YACjB,OAAO,WAAW,CAAC;SACpB;QACD,OAAO,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU;YACjD,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU;YAC3C,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,YAAY,CAAC;IACnB,CAAC,CAAC;IAEF,yEAAyE;IACzE,eAAe,CAAC,GAAG,EAAE;QACnB,2FAA2F;QAC3F,sBAAsB;QACtB,gCAAgC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACrD,2BAA2B,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAC3F,CAAC;QAEF,kFAAkF;QAClF,MAAM,YAAY,GAAG,uCAAuC,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxE,2BAA2B,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAC3F,CAAC;QACF,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,wBAAwB,CAAC;AAClC,CAAC","sourcesContent":["import { useLayoutEffect, useState } from 'react';\n\nimport { NotificationResponse } from './Notifications.types';\nimport {\n addNotificationResponseReceivedListener,\n getLastNotificationResponseAsync,\n} from './NotificationsEmitter';\n\ntype MaybeNotificationResponse = NotificationResponse | null | undefined;\n\n/**\n * A React hook always returns the notification response that was received most recently\n * (a notification response designates an interaction with a notification, such as tapping on it).\n *\n * > If you don't want to use a hook, you can use `Notifications.getLastNotificationResponseAsync()` instead.\n *\n * @return The hook may return one of these three types/values:\n * - `undefined` - until we're sure of what to return,\n * - `null` - if no notification response has been received yet,\n * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.\n *\n * @example\n * Responding to a notification tap by opening a URL that could be put into the notification's `data`\n * (opening the URL is your responsibility and is not a part of the `expo-notifications` API):\n * ```jsx\n * import * as Notifications from 'expo-notifications';\n * import { Linking } from 'react-native';\n *\n * export default function App() {\n * const lastNotificationResponse = Notifications.useLastNotificationResponse();\n * React.useEffect(() => {\n * if (\n * lastNotificationResponse &&\n * lastNotificationResponse.notification.request.content.data.url &&\n * lastNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER\n * ) {\n * Linking.openURL(lastNotificationResponse.notification.request.content.data.url);\n * }\n * }, [lastNotificationResponse]);\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport default function useLastNotificationResponse() {\n const [lastNotificationResponse, setLastNotificationResponse] =\n useState<MaybeNotificationResponse>(undefined);\n\n // Pure function that returns the new response if it is different from the previous,\n // otherwise return the previous response\n const newResponseIfNeeded = (\n prevResponse: MaybeNotificationResponse,\n newResponse: MaybeNotificationResponse\n ) => {\n // If the new response is undefined or null, no need for update\n if (!newResponse) {\n return prevResponse;\n }\n // If the previous response is undefined or null and the new response is not, we should update\n if (!prevResponse) {\n return newResponse;\n }\n return prevResponse.notification.request.identifier !==\n newResponse.notification.request.identifier\n ? newResponse\n : prevResponse;\n };\n\n // useLayoutEffect ensures the listener is registered as soon as possible\n useLayoutEffect(() => {\n // Get the last response first, in case it was set earlier (even in native code on startup)\n // before this renders\n getLastNotificationResponseAsync?.().then((response) =>\n setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response))\n );\n\n // Set up listener for responses that come in, and set the last response if needed\n const subscription = addNotificationResponseReceivedListener((response) =>\n setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response))\n );\n return () => {\n subscription.remove();\n };\n }, []);\n\n return lastNotificationResponse;\n}\n"]}
1
+ {"version":3,"file":"useLastNotificationResponse.js","sourceRoot":"","sources":["../src/useLastNotificationResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EACL,uCAAuC,EACvC,sCAAsC,EACtC,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAIhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B;IACjD,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,GAC3D,QAAQ,CAA4B,SAAS,CAAC,CAAC;IAEjD,oFAAoF;IACpF,yCAAyC;IACzC,MAAM,mBAAmB,GAAG,CAC1B,YAAuC,EACvC,WAAsC,EACtC,EAAE;QACF,+DAA+D;QAC/D,IAAI,CAAC,WAAW,EAAE;YAChB,OAAO,YAAY,CAAC;SACrB;QACD,8FAA8F;QAC9F,IAAI,CAAC,YAAY,EAAE;YACjB,OAAO,WAAW,CAAC;SACpB;QACD,OAAO,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU;YACjD,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU;YAC3C,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,YAAY,CAAC;IACnB,CAAC,CAAC;IAEF,yEAAyE;IACzE,eAAe,CAAC,GAAG,EAAE;QACnB,2FAA2F;QAC3F,sBAAsB;QACtB,gCAAgC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACrD,2BAA2B,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAC3F,CAAC;QAEF,kFAAkF;QAClF,MAAM,YAAY,GAAG,uCAAuC,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxE,2BAA2B,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAC3F,CAAC;QACF,MAAM,yBAAyB,GAAG,sCAAsC,CAAC,GAAG,EAAE;YAC5E,2BAA2B,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,MAAM,EAAE,CAAC;YACtB,yBAAyB,CAAC,MAAM,EAAE,CAAC;QACrC,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,wBAAwB,CAAC;AAClC,CAAC","sourcesContent":["import { useLayoutEffect, useState } from 'react';\n\nimport { NotificationResponse } from './Notifications.types';\nimport {\n addNotificationResponseReceivedListener,\n addNotificationResponseClearedListener,\n getLastNotificationResponseAsync,\n} from './NotificationsEmitter';\n\ntype MaybeNotificationResponse = NotificationResponse | null | undefined;\n\n/**\n * A React hook always returns the notification response that was received most recently\n * (a notification response designates an interaction with a notification, such as tapping on it).\n *\n * > If you don't want to use a hook, you can use `Notifications.getLastNotificationResponseAsync()` instead.\n *\n * @return The hook may return one of these three types/values:\n * - `undefined` - until we're sure of what to return,\n * - `null` - if no notification response has been received yet,\n * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.\n *\n * @example\n * Responding to a notification tap by opening a URL that could be put into the notification's `data`\n * (opening the URL is your responsibility and is not a part of the `expo-notifications` API):\n * ```jsx\n * import * as Notifications from 'expo-notifications';\n * import { Linking } from 'react-native';\n *\n * export default function App() {\n * const lastNotificationResponse = Notifications.useLastNotificationResponse();\n * React.useEffect(() => {\n * if (\n * lastNotificationResponse &&\n * lastNotificationResponse.notification.request.content.data.url &&\n * lastNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER\n * ) {\n * Linking.openURL(lastNotificationResponse.notification.request.content.data.url);\n * }\n * }, [lastNotificationResponse]);\n * return (\n * // Your app content\n * );\n * }\n * ```\n * @header listen\n */\nexport default function useLastNotificationResponse() {\n const [lastNotificationResponse, setLastNotificationResponse] =\n useState<MaybeNotificationResponse>(undefined);\n\n // Pure function that returns the new response if it is different from the previous,\n // otherwise return the previous response\n const newResponseIfNeeded = (\n prevResponse: MaybeNotificationResponse,\n newResponse: MaybeNotificationResponse\n ) => {\n // If the new response is undefined or null, no need for update\n if (!newResponse) {\n return prevResponse;\n }\n // If the previous response is undefined or null and the new response is not, we should update\n if (!prevResponse) {\n return newResponse;\n }\n return prevResponse.notification.request.identifier !==\n newResponse.notification.request.identifier\n ? newResponse\n : prevResponse;\n };\n\n // useLayoutEffect ensures the listener is registered as soon as possible\n useLayoutEffect(() => {\n // Get the last response first, in case it was set earlier (even in native code on startup)\n // before this renders\n getLastNotificationResponseAsync?.().then((response) =>\n setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response))\n );\n\n // Set up listener for responses that come in, and set the last response if needed\n const subscription = addNotificationResponseReceivedListener((response) =>\n setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response))\n );\n const clearResponseSubscription = addNotificationResponseClearedListener(() => {\n setLastNotificationResponse(undefined);\n });\n return () => {\n subscription.remove();\n clearResponseSubscription.remove();\n };\n }, []);\n\n return lastNotificationResponse;\n}\n"]}
@@ -9,6 +9,7 @@
9
9
 
10
10
  static NSString * const onDidReceiveNotification = @"onDidReceiveNotification";
11
11
  static NSString * const onDidReceiveNotificationResponse = @"onDidReceiveNotificationResponse";
12
+ static NSString * const onDidClearNotificationResponse = @"onDidClearNotificationResponse";
12
13
 
13
14
  @interface EXNotificationsEmitter : EXExportedModule <EXEventEmitter, EXModuleRegistryConsumer, EXNotificationsDelegate>
14
15
 
@@ -28,6 +28,13 @@ EX_EXPORT_METHOD_AS(getLastNotificationResponseAsync,
28
28
  resolve(lastResponse ? [self serializedNotificationResponse:lastResponse] : [NSNull null]);
29
29
  }
30
30
 
31
+ EX_EXPORT_METHOD_AS(clearLastNotificationResponseAsync,
32
+ clearLastNotificationResponseAsyncWithResolver:(EXPromiseResolveBlock)resolve reject:(EXPromiseRejectBlock)reject)
33
+ {
34
+ _notificationCenterDelegate.lastNotificationResponse = nil;
35
+ resolve([NSNull null]);
36
+ }
37
+
31
38
  # pragma mark - EXModuleRegistryConsumer
32
39
 
33
40
  - (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
@@ -40,7 +47,7 @@ EX_EXPORT_METHOD_AS(getLastNotificationResponseAsync,
40
47
 
41
48
  - (NSArray<NSString *> *)supportedEvents
42
49
  {
43
- return @[onDidReceiveNotification, onDidReceiveNotificationResponse];
50
+ return @[onDidReceiveNotification, onDidReceiveNotificationResponse, onDidClearNotificationResponse];
44
51
  }
45
52
 
46
53
  - (void)startObserving
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-notifications",
3
- "version": "0.28.17",
3
+ "version": "0.28.18",
4
4
  "description": "Notifications module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,5 +55,5 @@
55
55
  "peerDependencies": {
56
56
  "expo": "*"
57
57
  },
58
- "gitHead": "fdcb7998e05af735c9bb9881006b2ee38cc218f2"
58
+ "gitHead": "04e325d4fc3b8a7ff20ac21f74dcf92da6294b40"
59
59
  }
@@ -10,6 +10,7 @@ const emitter = new EventEmitter(NotificationsEmitterModule);
10
10
  const didReceiveNotificationEventName = 'onDidReceiveNotification';
11
11
  const didDropNotificationsEventName = 'onNotificationsDeleted';
12
12
  const didReceiveNotificationResponseEventName = 'onDidReceiveNotificationResponse';
13
+ const didClearNotificationResponseEventName = 'onDidClearNotificationResponse';
13
14
 
14
15
  // @docsMissing
15
16
  export const DEFAULT_ACTION_IDENTIFIER = 'expo.modules.notifications.actions.DEFAULT';
@@ -109,9 +110,13 @@ export function removeNotificationSubscription(subscription: Subscription) {
109
110
  emitter.removeSubscription(subscription);
110
111
  }
111
112
 
112
- // @docsMissing
113
113
  /**
114
- * @header listen
114
+ * Gets the notification response that was received most recently
115
+ * (a notification response designates an interaction with a notification, such as tapping on it).
116
+ *
117
+ * - `null` - if no notification response has been received yet
118
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received
119
+ * - a [`NotificationResponse`](#notificationresponse) object - if a notification response was received.
115
120
  */
116
121
  export async function getLastNotificationResponseAsync(): Promise<NotificationResponse | null> {
117
122
  if (!NotificationsEmitterModule.getLastNotificationResponseAsync) {
@@ -121,3 +126,29 @@ export async function getLastNotificationResponseAsync(): Promise<NotificationRe
121
126
  const mappedResponse = response ? mapNotificationResponse(response) : response;
122
127
  return mappedResponse;
123
128
  }
129
+
130
+ /* Clears the notification response that was received most recently. May be used
131
+ * when an app selects a route based on the notification response, and it is undesirable
132
+ * to continue selecting the route after the response has already been handled.
133
+ * to continue to select the route after the response has already been handled.
134
+ *
135
+ * If a component is using the [`useLastNotificationResponse`](#useLastNotificationResponse) hook,
136
+ * this call will also clear the value returned by the hook.
137
+ *
138
+ * @return A promise that resolves if the native call was successful.
139
+ */
140
+ export async function clearLastNotificationResponseAsync(): Promise<void> {
141
+ if (!NotificationsEmitterModule.clearLastNotificationResponseAsync) {
142
+ throw new UnavailabilityError('ExpoNotifications', 'getLastNotificationResponseAsync');
143
+ }
144
+ await NotificationsEmitterModule.clearLastNotificationResponseAsync();
145
+ // Emit event to clear any useLastNotificationResponse hooks, after native call succeeds
146
+ emitter.emit(didClearNotificationResponseEventName, []);
147
+ }
148
+
149
+ /**
150
+ * @hidden
151
+ */
152
+ export function addNotificationResponseClearedListener(listener: () => void): Subscription {
153
+ return emitter.addListener<void>(didClearNotificationResponseEventName, listener);
154
+ }
@@ -3,6 +3,7 @@ import { useLayoutEffect, useState } from 'react';
3
3
  import { NotificationResponse } from './Notifications.types';
4
4
  import {
5
5
  addNotificationResponseReceivedListener,
6
+ addNotificationResponseClearedListener,
6
7
  getLastNotificationResponseAsync,
7
8
  } from './NotificationsEmitter';
8
9
 
@@ -80,8 +81,12 @@ export default function useLastNotificationResponse() {
80
81
  const subscription = addNotificationResponseReceivedListener((response) =>
81
82
  setLastNotificationResponse((prevResponse) => newResponseIfNeeded(prevResponse, response))
82
83
  );
84
+ const clearResponseSubscription = addNotificationResponseClearedListener(() => {
85
+ setLastNotificationResponse(undefined);
86
+ });
83
87
  return () => {
84
88
  subscription.remove();
89
+ clearResponseSubscription.remove();
85
90
  };
86
91
  }, []);
87
92