[expo-notifications] Add useLastNotificationResponse hook#10883
[expo-notifications] Add useLastNotificationResponse hook#10883
Conversation
0393f63 to
b1e275f
Compare
e2fd3f9 to
5191e72
Compare
5fe5ddd to
e909084
Compare
cruzach
left a comment
There was a problem hiding this comment.
I tested this (using the code from this snack), and I'm consistently getting the initial (i.e. app-launching) notification response!! 🎉 only thing I want to bring up is that I'm seeing some different behavior on iOS vs Android when using both useLastNotificationResponse and addNotificationResponseReceivedListener at the same time. I'm not sure about a use case that would use both, but just because the behavior was different on each platform I thought it might be worth bringing up here:
iOS
- only
useLastNotificationResponsetriggered if app is dead & opened with notification - only
addNotificationResponseReceivedListenercalled if app is foregrounded or backgrounded & you tap on a notification
Android
- only
useLastNotificationResponsetriggered if app is dead & opened with notification - both hook AND listener called if app is foregrounded or backgrounded
Sidenote- looks like RN is also sending a warning when you open the app via a notification (this happened to me in development on iOS):
Sending notification when app is killed, on open: Sending
onDidReceiveNotificationResponsewith no listeners registered.
Should/could we silence that?
cruzach
left a comment
There was a problem hiding this comment.
sorry- forgot to add this to the last review
| mNotificationManager.removeListener(this); | ||
| } | ||
|
|
||
| public void getLastNotificationResponseAsync(Promise promise) { |
There was a problem hiding this comment.
should this be an @ExpoMethod?
There was a problem hiding this comment.
Of coourse! Thank you for catching that, I was so worked up on iOS not working I forgot to test Android!
The listener will be reused by two hooks — useLastNotificationResponse and useInitialNotificationResponse
…SharedNotificationResponseListener
…ing from undefined state more quickly BTW also making EXNotificationsEmitter always listen to events from EXNotificationCenterDelegate
…hich could remove `useLastNotificationResponse` listeners
c02e294 to
fe0bdb8
Compare
Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com>
3665d66 to
3dc5eb4
Compare
|
I have now:
|
cruzach
left a comment
There was a problem hiding this comment.
LGTM 🙌
Last question- from the looks of it, I don't think any scoped Android code needs to be updated, but EXScopedNotificationsEmitter.m does need to be updated so that this fix lands in the managed workflow for SDK 40? I suppose it might make more sense for that to land in a separate PR though (up to you)
|
Thank you for catching that! 👁️ 🕵️ 3953aa4 should take care of it by changing the way we override serialization mechanism and thanks to that allowing us to call |
cruzach
left a comment
There was a problem hiding this comment.
perfect! thanks for adding that in so quickly 🏎️
3953aa4 to
9f85299
Compare
|
Sorry to ask here, but is this hook the recommended way of handling notification presses? The guide does not use it, but it's a class component: https://docs.expo.io/push-notifications/receiving-notifications/. It also seems to use the same API as this hook does under the hood. Currently trying to migrate to |
|
@SimenB Yes, but this hook landed as part of SDK 40 (which is currently in beta) You can see documentation for it here, but since it's still in beta i think we're going to keep the example you linked to the same for now 👍 |
| initialNotificationResponse.notification.data.url && | ||
| initialNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER | ||
| lastNotificationResponse && | ||
| lastNotificationResponse.notification.data.url && |
There was a problem hiding this comment.
@sjchmiela I was wondering if this is the correct way to access notification.data, since lastNotificationResponse contain the response from addNotificationResponseReceivedListener. Shouldn't it be notification.request.content.data ?
Yep, I'm testing with the beta 👍 Thanks for the response, 🤞 this works out for us |
…nly once JS subscribes to it (#11382) # Why Fixes a bug introduced in #10883 which causes initial notification responses to get lost in standalone iOS apps. Along with #11378 I believe it fixes #11343 and may also finally fix #9866. # How Using native breakpoints I've noticed `EXNotificationCenterDelegate`'s `addDelegate:` is called more times than I would expect it to. It turned out before `EXScopedNotificationsEmitter` was subscribing to `EXNotificationCenterDelegate` (it would then receive pending notification response) an unscoped `EXNotificationsEmitter` was subscribing and consuming pending responses. Since unscoped emitter wasn't being used and exposed to the app later, it consumed the response into the void. Most probably unimodules have a bug where instances of overridden modules are still kept in memory (since `setModuleRegistry:` is called on them). Fixing this bug is out of the scope of this pull request. These changes are based on how it was implemented before dfda625. I can't see any reason why `EXNotificationsEmitter` would need to register for notifications as soon as module registry is ready, so let's roll back to what we know worked well. # Test Plan I have verified in an ExpoKit workspace that when the app is opened from a notification, the notification response is delivered to `useLastNotificationResponse`: https://www.loom.com/share/586a906c538f47f0940b2cc83582fb29
…nly once JS subscribes to it (#11382) # Why Fixes a bug introduced in #10883 which causes initial notification responses to get lost in standalone iOS apps. Along with #11378 I believe it fixes #11343 and may also finally fix #9866. # How Using native breakpoints I've noticed `EXNotificationCenterDelegate`'s `addDelegate:` is called more times than I would expect it to. It turned out before `EXScopedNotificationsEmitter` was subscribing to `EXNotificationCenterDelegate` (it would then receive pending notification response) an unscoped `EXNotificationsEmitter` was subscribing and consuming pending responses. Since unscoped emitter wasn't being used and exposed to the app later, it consumed the response into the void. Most probably unimodules have a bug where instances of overridden modules are still kept in memory (since `setModuleRegistry:` is called on them). Fixing this bug is out of the scope of this pull request. These changes are based on how it was implemented before dfda625. I can't see any reason why `EXNotificationsEmitter` would need to register for notifications as soon as module registry is ready, so let's roll back to what we know worked well. # Test Plan I have verified in an ExpoKit workspace that when the app is opened from a notification, the notification response is delivered to `useLastNotificationResponse`: https://www.loom.com/share/586a906c538f47f0940b2cc83582fb29
…nly once JS subscribes to it (#11382) # Why Fixes a bug introduced in expo/expo#10883 which causes initial notification responses to get lost in standalone iOS apps. Along with #11378 I believe it fixes #11343 and may also finally fix #9866. # How Using native breakpoints I've noticed `EXNotificationCenterDelegate`'s `addDelegate:` is called more times than I would expect it to. It turned out before `EXScopedNotificationsEmitter` was subscribing to `EXNotificationCenterDelegate` (it would then receive pending notification response) an unscoped `EXNotificationsEmitter` was subscribing and consuming pending responses. Since unscoped emitter wasn't being used and exposed to the app later, it consumed the response into the void. Most probably unimodules have a bug where instances of overridden modules are still kept in memory (since `setModuleRegistry:` is called on them). Fixing this bug is out of the scope of this pull request. These changes are based on how it was implemented before expo/expo@dfda625. I can't see any reason why `EXNotificationsEmitter` would need to register for notifications as soon as module registry is ready, so let's roll back to what we know worked well. # Test Plan I have verified in an ExpoKit workspace that when the app is opened from a notification, the notification response is delivered to `useLastNotificationResponse`: https://www.loom.com/share/586a906c538f47f0940b2cc83582fb29
…nly once JS subscribes to it (#11382) # Why Fixes a bug introduced in expo/expo#10883 which causes initial notification responses to get lost in standalone iOS apps. Along with #11378 I believe it fixes #11343 and may also finally fix #9866. # How Using native breakpoints I've noticed `EXNotificationCenterDelegate`'s `addDelegate:` is called more times than I would expect it to. It turned out before `EXScopedNotificationsEmitter` was subscribing to `EXNotificationCenterDelegate` (it would then receive pending notification response) an unscoped `EXNotificationsEmitter` was subscribing and consuming pending responses. Since unscoped emitter wasn't being used and exposed to the app later, it consumed the response into the void. Most probably unimodules have a bug where instances of overridden modules are still kept in memory (since `setModuleRegistry:` is called on them). Fixing this bug is out of the scope of this pull request. These changes are based on how it was implemented before expo/expo@dfda625. I can't see any reason why `EXNotificationsEmitter` would need to register for notifications as soon as module registry is ready, so let's roll back to what we know worked well. # Test Plan I have verified in an ExpoKit workspace that when the app is opened from a notification, the notification response is delivered to `useLastNotificationResponse`: https://www.loom.com/share/586a906c538f47f0940b2cc83582fb29
Why
Idea inspired by @cruzach sounded! #10811 (review)
How
SharedNotificationResponseListener.fx.tsfileuseInitialNotificationResponseimplementation to rely on ituseLastNotificationResponsewhich is like a notification response swiss knife:undefinedornullor not)Frankly speaking I'm not 100% sure how big of a deal is leaving a dangling listener active, but I can't think of any reason why it would be a problem.
Test Plan
I have verified this hook returns latest notification response if the hook is mounted as (early in the app as possible and after some time from starting the app) ✖️ (the app is started in response to notification tap, notification tap while the app is running)