Skip to content

fix(android-client): reflect swipe-dismissed and timed-out ongoing notifications in the hook - #355

Merged
V3RON merged 5 commits into
mainfrom
fix/android-ongoing-notification-dismissal
Oct 16, 2026
Merged

V3RON merged 5 commits into
mainfrom
fix/android-ongoing-notification-dismissal

Conversation

@V3RON

@V3RON V3RON commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What is this?

useAndroidOngoingNotification() keeps saying a notification is active after the user swipes it away or its timeoutMs runs out. The device already records the dismissal (getAndroidOngoingNotificationStatus() reports isDismissed: true), but the hook never learns about it. Once a notification has been dismissed, start() with the same notificationId returns already_exists and posts nothing, so the hook cannot bring it back until something calls stop first.

This fixes both. The hook's isActive now follows the device, and start() works again after a dismissal. The decision is recorded in ADR 0012.

How does it work?

  • Native "ended" signal. Android gains its first native-to-JavaScript event, an internal TurboModule event emitter. Native code fires it when a notification is dismissed (swipe or timeout, both delivered through the delete intent) or stopped (stop or endAll, from anywhere in the app). The hook subscribes when it mounts, then reads the native status once, so a change that lands between the two is not missed. It clears its state when the event names its notification. The event is not public API.
  • start() replaces a dismissed record. A record marked dismissed no longer blocks a new start with the same id: it is replaced with a fresh one and posted again. update and upsert still reject a dismissed notification with reason: 'dismissed', so a server push cannot bring back a notification the user swiped away.
  • autoStart runs once. It runs on mount, or when the option turns on, and no longer re-runs whenever the hook goes inactive. A notification the user dismisses stays dismissed while the component is mounted, and end() no longer restarts it immediately. The next mount with autoStart posts it again, since a dismissed notification no longer blocks a start.

The example app's Ongoing Notifications tab gets a Hook card that shows the hook's isActive next to the native status, which is how this was reproduced and verified on an emulator.

Why is this useful?

Apps that drive ongoing notifications through the hook can trust isActive, for example to show a "Resume tracking" button after the user dismisses the notification, and calling start() again simply works. Before this change the hook stayed stuck as active and the notification could not be posted again under the same id.

@V3RON
V3RON marked this pull request as ready for review October 15, 2026 12:46
V3RON added 5 commits October 16, 2026 09:55
…tifications in the hook

Native code now reports when a recorded ongoing notification ends
(dismissed by the user or a timeout, or stopped) through an internal
TurboModule event, and useAndroidOngoingNotification clears its state
when it hears about its notification. start() replaces a dismissed
record instead of failing with already_exists, while update and upsert
keep refusing to resurrect it. autoStart runs on mount or when it turns
on, not whenever the hook becomes inactive. See ADR 0012.
… notification

Address review: a start over a dismissed record reuses its system
notification id so a still-visible copy is replaced in place, the hook
tolerates a missing native event emitter, and the docs, changeset and
ADR spell out the remount and start-from-push consequences.
Shows useAndroidOngoingNotification's isActive next to the native status,
with start, end, autoStart and a 10-second timeout, to check the hook
against swipes, timeouts and cold starts on a device.
@V3RON
V3RON force-pushed the fix/android-ongoing-notification-dismissal branch from 2a2872a to 115ef0b Compare October 16, 2026 07:57
@V3RON
V3RON merged commit 58f0fd4 into main Oct 16, 2026
16 checks passed
@V3RON
V3RON deleted the fix/android-ongoing-notification-dismissal branch October 16, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant