Repository navigation
Drop chat notifications for an account that is not signed in - #29804
Merged
Merged
Conversation
Every NotifyChat notification now names the account it was made for (#29708). Login and logout are not serialized against them, so an account switch can deliver the previous account's late. _onEngineIncoming drops any NotifyChat whose uid is not the signed-in account's, and all of them while no account is signed in, before the chat router or any engine action listener sees it. chatUi calls carry no uid and pass through. The per-handler uid check for left/reset conversations is now redundant and removed.
The leaving account's ChatInboxSynced is now dropped as another account's, so the inbox layout reset clears the sync key itself. Rename the filter to say it also drops everything while no account is signed in.
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No blocking issues remain; regression coverage addresses account filtering, chatUi passthrough, and sync cleanup.
No open issues 🎉
What changed in this PR
Prevents late chat notifications from a signed-out account from reaching the GUI’s chat stores or engine listeners.
Changes:
- Filters NotifyChat events by signed-in UID while preserving chatUi calls.
- Clears inbox sync waiting state during account changes.
- Updates regression tests and documents the filtering behavior.
| File | Description |
|---|---|
| shared/constants/init/shared.tsx | Filters notifications before routing or listener delivery. |
| shared/chat/readme.md | Documents account filtering. |
| shared/chat/notification-router.tsx | Adds the UID predicate and simplifies conversation removal. |
| shared/chat/notification-effects.test.tsx | Tests filtering, listener delivery, and sync cleanup. |
| shared/chat/inbox/selection.tsx | Removes the redundant per-handler UID check. |
| shared/chat/inbox/layout-state.tsx | Clears sync waiting state on reset. |
| shared/chat/inbox/auto-select-after-switch.test.tsx | Updates selection coverage for centralized filtering. |
Review effort: Balanced
This was referenced Oct 26, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every
chat.1.NotifyChat.*notification now names the account it was made for (#29708). The GUI uses that:_onEngineIncomingdrops any NotifyChat whoseuidis not the signed-in account's, before the chat notification router or any engine action listener sees it. While no account is signed in (current uid'', from the start of a switch or a logout until the next bootstrap) all of them are dropped.chat.1.chatUi.*calls carry no uid and pass through untouched.Why
Login and logout are not serialized against chat notifications, so through an account switch the previous account's can still arrive. Until now the GUI ignored the uid on all but two of them, so a late notification could write the previous account's metas, typing, participants or archive progress into the next account's stores, or into the next account's thread for a team channel both accounts share.
Changes
chat/notification-router.tsx:isChatNotificationNotForSignedInAccount, the predicate, covering every NotifyChat type (including ones the router does not route: archive progress/complete, welcome message, team retention).constants/init/shared.tsx:_onEngineIncomingreturns early on it.chat/inbox/selection.tsx:conversationGoneForUseris gone; the router callsconversationGonefor left/reset conversations, since the central filter already checks the account.chat/inbox/layout-state.tsx: the inbox layout reset also clearswaitingKeyChatInboxSyncStarted. That key is held by sync notifications rather than a call, and the leaving account's closingChatInboxSyncedis now dropped, so nothing else would release it and the inbox would show loading.chat/readme.md: describes the filter.Judgment calls
''also drops the new account's earliest notifications (before its bootstrap lands). The inbox does a full refresh once the session is ready, and letting notifications through in that window would let the previous account's through too.isRetired,makeThreadChatRpc) and the engine's account-generation checks stay. They guard screens kept mounted through a switch from starting calls as the next account and late call results from the previous one, which a notification filter does not cover. The per-thread notification guard (useConversationThreadNotifications) also stays: it stops the new account's notifications for a shared channel reaching the old account's still-mounted thread, and those carry the current uid.Tests
chat/notification-effects.test.tsx, through the real_onEngineIncomingand engine listener bus:Each was checked to fail with its fix removed. The suite's notification builder now stamps the signed-in uid on NotifyChat params.
auto-select-after-switch.test.tsxdrops its other-account step, which tested the removed per-handler check by calling the router directly.yarn lint:allclean,yarn test:unitpassing.