Skip to content

fix(chat): don't rejoin the room after leaving a chat - #6916

Closed
mahibi wants to merge 2 commits into
masterfrom
fixWebsocketNotClosed
Closed

mahibi wants to merge 2 commits into
masterfrom
fixWebsocketNotClosed

Conversation

@mahibi

@mahibi mahibi commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

not yet tested!

  • Symptom

    • After leaving a chat (Back or Home), the signaling websocket kept receiving messages for that room and no push notifications arrived. The server still had a session for the user in the room.
  • Cause 1: rejoin right after leaving (fixed in f9461f957)

    • When the leave REST call completes, ChatViewModel.leaveRoom() resets getCapabilitiesViewState to GetCapabilitiesStartState.
    • conversationFlow re-emits when lastReadMessage or lastCommonReadMessage changes. The latter was added in 61ba4e8 and comes e.g. from the conversation list's room sync. That emission turns into GetCapabilitiesInitialLoadState.
    • ChatActivity stays STARTED after onPause until onStop. After finish(), onStop can come up to ~10 s later, so its observer called joinRoomWithPassword() and joined the room again (REST + websocket).
    • With Home, the value was delivered in onStart. If nothing emitted while the app was in the background, the chat did not rejoin at all on return.
  • Fix 1

    • The room is only joined while ChatActivity is resumed. A join requested between onPause and onResume is deferred to onResume.
    • A left room is always rejoined in onResume, independent of conversation emissions.
    • No second REST join is started while one is running.

    Cause 2: cancelled join (fixed in 3c76ebf6e)

    • ChatViewModel.onPause() disposed a join that was still running. The server could still create the session, while onPause saw no valid session and did not leave. The session stayed until the server timed it out.
  • Fix 2

    • The join keeps running across onPause. If the chat was left in the meantime, the ViewModel leaves via REST (in appScope, so it also works after Back) as soon as the join completes, and the join is not reported to the activity.
    • Resuming before the join completes cancels the pending leave.
    • The "join running" state lives in the ViewModel, so a rotation doesn't start a second join.
  • Not changed

    • WebSocketInstance still keeps currentRoomToken on leave. It doesn't affect this bug: the session is cleared on leave, and the server's reply to the leave clears the token.
    • The GetCapabilitiesStartState reset in ChatViewModel.leaveRoom() is still there and could be removed as a follow-up.
  • How to test

    • Open a chat and leave it with Back, then with Home. After leaveRoom completed there should be no sessionID was not valid -> joinRoom and no Sending join room message via websocket.
    • After Home, returning should join exactly once, after onResume.
    • Leave a chat right after opening it, while the join is still running. You should see join in progress -> leaving room once it completes, then joinRoom completed after the chat was left -> leaving the room again.
    • Check that pushes for that room arrive again after leaving.

馃弫 Checklist

  • 鉀戯笍 Tests (unit and/or integration) are included or not needed
  • 馃敄 Capability is checked or not needed
  • 馃敊 Backport requests are created or not needed: /backport to stable-xx.x
  • 馃搮 Milestone is set
  • 馃尭 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

馃 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Leaving a chat sometimes did not take effect: the signaling websocket
kept receiving messages for the room and no push notifications arrived.

ChatViewModel.leaveRoom() resets the capabilities state to
GetCapabilitiesStartState once the leave request completes. Any later
conversation emission (since 61ba4e8 also lastCommonReadMessage
changes, e.g. from the room list sync of the conversation list) then
emits GetCapabilitiesInitialLoadState. ChatActivity is still STARTED
after onPause until onStop arrives, which can take a while after
finish(), so its observer called joinRoomWithPassword() and joined the
room again right after leaving it. With the Home button the value was
delivered in onStart instead, and if nothing emitted in the background
the room was not joined again at all on return.

Only join the room while the chat is resumed: a join requested between
onPause and onResume is deferred until onResume, and a left room is
always joined again on the next resume. Also skip a second REST join
while one is already running.

Assisted-by: Claude-Code:claude-opus-5-5
ChatViewModel.onPause disposed a join request that was still running.
The request may already have reached the server, which then kept a
session in the room that the app never knew about: onPause saw no valid
session and did not leave, so the server only dropped it on timeout.

Keep the join request running across onPause instead. If the chat is
left while it runs, the room is left again via REST as soon as the join
completes, without reporting the join to the activity (so no websocket
join is sent). The leave runs in appScope, so it is also sent after the
chat was closed with Back. Resuming the chat before the join completes
cancels the pending leave and the join is reported as usual.

The running join is tracked in ChatViewModel instead of ChatActivity, so
it also survives a configuration change and no second join is started.

Assisted-by: Claude-Code:claude-opus-5-5
@mahibi mahibi added this to the 25.1.0 milestone Oct 16, 2026
@mahibi mahibi self-assigned this Oct 16, 2026
@mahibi mahibi changed the title Fix websocket not closed fix(chat): don't rejoin the room after leaving a chat Oct 16, 2026
@mahibi

mahibi commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator Author

oh that was coincidence..
i had this as a prompt for 2 weeks and finally found the time for it but it seems @ToteMeiSter also found this problem and seems to address it with #6909

It will take a closer look on monday. So i might close my PR in favor of #6909

@github-actions

Copy link
Copy Markdown
Contributor

馃摫 QA build

Download app-qa-debug.apk
QR code Open the QR code for this download
Commit c22770f
Version 6916
Available until 7 days after this build

The QA build installs alongside a released Nextcloud app, so you can keep
using your existing install while testing.

Downloading the file requires a GitHub account, so open this link on the
device you want to test on, or transfer the APK to it.

@mahibi

mahibi commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

closing in favor of #6909

@mahibi mahibi closed this Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant