Repository navigation
fix(chat): join the room on resume, as the counterpart of leaving on pause - #6909
Merged
Merged
Conversation
1 of 6 tasks
…pause The chat left the room in onPause, but joined it from the first capabilities state after a reset to the initial load. leaveRoom and every onSaveInstanceState reset that state, so the next refresh of the conversation joined the room again. LiveData delivers to a started observer, so a refresh between onPause and onStop joined the room right after it was left. Nothing leaves it again, the session stayed in the room, and the server sent no push while its last ping was fresh. After a return from the background the join also depended on such a refresh. Join from onResume once the conversation is known, and from the initial load while the screen is resumed, at most once per resume. Stop resetting the capabilities state in leaveRoom, and reset it in onSaveInstanceState only when the activity is recreated for a configuration change. The initial load no longer runs again on a return to the chat, so onResume repeats what it did that depends on the current state: the shared files of a new intent, the focus of the input, the scheduled messages, the upcoming event, the out-of-office status and the room refresh timer. Assisted-by: Claude-Code:claude-sonnet-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
The conversation shown in the message list can be set before the capabilities are loaded, for example when the screen was left before the answer of a federated server. A return to the chat then joined the room and focused the input before the initial load, and a call started by the join read capabilities that were not set yet. Track the first initial load of the screen and join and run the return actions only after it. Focus the input only when its fragment is added. Cover a configuration change in the viewmodel test and release the viewmodel and its scope after each test. Assisted-by: Claude-Code:claude-sonnet-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
A return to the chat while the leave of onPause was still running joined the room at once. The server could handle the leave after the join, and the late leave success cleared the current room holder and cancelled the room timer that the return had started again. Join only after a running leave and cancel that wait on pause. Cancel the room timer on leave success only while the leave is still wanted. A failed first load of federated capabilities left the error state, so every later load was an update and the chat never joined the room. Treat the error state as a pending initial load. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Since 8adb868 the chat leaves the signaling room and drops its session at the start of leaveRoom, but ApplicationWideCurrentRoomHolder kept the session until the leave success, as fd4fc9b put it there. When the chat was closed before that success, its observer was already removed and the holder was never cleared. A chat opened again for the room then reused the left session, skipped the join and was not in the room for the server, which sent pushes for its messages. Clear the holder together with the session when the leave starts. The leave runs only without an active call, so a late leave success no longer resets the state of a call started in the meantime. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
mahibi
force-pushed
the
fix/chat-rejoin-on-resume
branch
from
October 19, 2026 15:31
ba69929 to
9860f32
Compare
…load A failed load of federated capabilities was treated as a pending initial load even after the initial load was delivered. The capabilities of a federated conversation are loaded on every refresh, so one failed refresh made the next one an initial load again: the chat showed the deletion warnings again, started a second room timer and replaced the input fragment. Track whether the initial load was delivered and treat the error as pending only before that. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
mahibi
approved these changes
Oct 19, 2026
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.
Problem
After leaving a chat the app sometimes joins the room again 35-300 ms later (
DELETE .../participants/active, thenPOST .../participants/active). The session stays in the room until the next leave, minutes later. While its last ping is fresh the server treats the user as online and sends no push for new messages.The chat leaves the room in
onPause, but joined it from the first capabilities state after a reset to the initial load.ChatViewModel.leaveRoomand everyonSaveInstanceStateresetgetCapabilitiesViewState, so the next refresh of the conversation emittedGetCapabilitiesInitialLoadStateandChatActivityjoined the room. LiveData delivers to a started observer, so a refresh betweenonPauseandonStopjoined the room right after it was left.onDestroydoes not leave it. After a return from the background the join also depended on such a refresh.Fix
onResumecallsensureJoined()once the first initial load of the screen is done (the conversation can be set by the message list before the capabilities are loaded). The initial load observer calls it only while the screen is resumed, for the first open.ChatViewModel.claimRoomJoin()allows one join per resume and is released inChatViewModel.onPause, where the pending join is disposed as well.leaveRoomno longer resets the capabilities state.onSaveInstanceStateresets it only whenisChangingConfigurationsis true, where the new activity needs the initial load to build its UI; a stop without a configuration change keeps the state.onResumerepeats what depends on the current state: shared files of a new intent, focus of the input, scheduled messages, upcoming event, out-of-office status and the room refresh timer. The deletion warnings of event and ended-call rooms are not shown again on a return.Tests
ChatViewModelRoomJoinTestuses the realChatViewModelwith mocked repositories: a refresh of the conversation afterleaveRoomis not an initial load, and leave, refresh, return without a configuration change joins exactly once per resume. It also covers a configuration change. The first two tests fail on master. The wiring inChatActivity(onResume, the initial load flag, theisChangingConfigurationscheck inonSaveInstanceState) is not covered by a unit test.Known remaining issues
onPause, no leave is sent, the session expires after about 30 s. Same as before.🏁 Checklist
/backport to stable-xx.x🤖 AI
Tested on
🤖 Generated with Claude Code