RocketChat / RocketChat/Rocket.Chat.ReactNative

[iOS] Stale video conference notification re-dispatched on every cold boot due to missing deduplication

Open
#7,015 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: bug
Dominant language
TypeScript
Stars
2.4k
Forks
1.5k
Avg merge
1d 18h
Merged PRs (30d)
90

Description

On iOS, when a user taps "Accept" or "Decline" on a video conference push notification, the app correctly processes the action. However, Expo’s getLastNotificationResponseAsync() / getLastNotificationResponse() does not clear the last notification response after it is read.

Because of this, the same stale notification persists across cold boots (force-close → reopen from app icon). Every time the app launches normally, it re-processes the old video conference notification and dispatches deepLinkingClickCallPush again.

This causes users to be repeatedly forced into an old, already-ended video call.


Root Cause

There is no deduplication logic in the notification handling pipeline.

  • No notification ID is stored after processing.
  • No check exists to verify whether a notification has already been handled.
  • Expo persists the last notification response across cold boots by design.

As a result, the same notification is dispatched repeatedly.


Affected Code Paths

Path 1

app/lib/notifications/push.ts (around line 277)

  • Calls Notifications.getLastNotificationResponse()
  • Immediately returns the transformed notification
  • No ID check

Flows into:

app/lib/notifications/index.ts (lines 42–44)

  • If notificationType === 'videoconf'
  • Immediately dispatches deepLinkingClickCallPush
  • No deduplication check

Path 2 (Backup Path)

app/lib/notifications/videoConf/getInitialNotification.ts (lines 56–75)

  • Calls getLastNotificationResponseAsync()
  • Parses ejson
  • If notificationType === 'videoconf'
  • Immediately dispatches deepLinkingClickCallPush
  • No deduplication check

Saga Handler

app/sagas/deepLinking.js (handleClickCallPush)

  • No staleness check
  • No timestamp validation
  • Attempts to join any video call regardless of age

Environment

  • Rocket.Chat Server Version: Any
  • Rocket.Chat App Version: Latest (develop branch)
  • Device: Any iOS device
  • OS Version: iOS 15+

Steps to Reproduce

  1. Receive a video conference push notification on iOS.
  2. Long-press the notification and tap Accept.
  3. App opens and joins the call.
  4. End the call.
  5. Force-close the app.
  6. Wait any amount of time.
  7. Reopen the app normally (tap app icon).
Observed Result
  • The app attempts to join the same old, ended video call.
  • Force-close and reopen again → same behavior.
  • This repeats indefinitely until another notification is tapped.

Expected Behavior

When opening the app normally (not from a notification):

  • App should open to the home screen or last viewed room.
  • A previously processed video conference notification should never be re-processed.

Actual Behavior

Every cold boot re-processes the same stale video conference notification and dispatches deepLinkingClickCallPush, forcing the user into an old call.

This continues indefinitely until a new notification interaction replaces the stored response.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the notification flow through app/lib/notifications/push.ts, app/lib/notifications/index.ts, and app/lib/notifications/videoConf/getInitialNotification.ts, then inspect handleClickCallPush in app/sagas/deepLinking.js. Reproduce the cold-boot behavior on iOS and identify how both paths process the persisted response. Done means a previously handled video conference response is not dispatched again after force-close and normal relaunch.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, typescript
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.