Skip to content

Update the message read status when the reading member is removed from the channel#6579

Merged
andremion merged 2 commits into
developfrom
andrerego/and-1310-compose-message-read-status-is-not-updated-when-the-reading
Jul 23, 2026
Merged

Update the message read status when the reading member is removed from the channel#6579
andremion merged 2 commits into
developfrom
andrerego/and-1310-compose-message-read-status-is-not-updated-when-the-reading

Conversation

@andremion

@andremion andremion commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Goal

When the only member who read a message is removed from the channel, the message delivery status should fall back from READ (double checkmark) to SENT (single checkmark), because no remaining member has read it. Currently the status stays READ after the member.removed event: the member is removed from the state, but their read entry is kept, so both the Compose and XML message lists keep showing the double checkmark. The iOS SDK already behaves correctly by deleting the removed member's read state.

Resolves AND-1310

Implementation

On member.removed, the removed member's ChannelUserRead is now deleted together with the member, in all three places that hold it:

  • In-memory state: ChannelEventHandlerImpl calls the new ChannelStateImpl.removeRead(userId).
  • Legacy state: ChannelEventHandlerLegacyImpl calls the new ChannelStateLogic.deleteRead(userId), which delegates to ChannelStateLegacyImpl.
  • Offline storage: the Channel.removeMember extension (used by EventHandlerSequential to persist the event) now also filters the removed user's entry out of Channel.read, so a cold start does not restore the stale READ status.

The scope is member.removed only, matching the iOS SDK. notification.removed_from_channel and notification.invite_rejected are unchanged.

Since MessageListController computes the read status from ChannelState.reads, the fix applies to both the Compose and XML UI kits.

The two e2e tests ported in #6572 are no longer ignored and act as the acceptance check:

  • test_readByDecremented_whenParticipantIsRemoved
  • test_readByDecrementedInThreadReply_whenParticipantIsRemoved

Testing

Manual steps:

  1. Log in with user A and open a channel that also has member B.
  2. Send a message as user A.
  3. Read the message as user B. User A sees a double checkmark below the message.
  4. Remove user B from the channel (for example, from the channel info screen or via a server-side call).
  5. The indicator below the message falls back to a single checkmark.

The same steps apply to a thread reply (step 2: reply in a thread instead).

Automated coverage:

  • New unit tests for ChannelStateImpl.removeRead, ChannelStateLegacyImpl.deleteRead, both event handlers, and the Channel.removeMember extension. :stream-chat-android-client:testDebugUnitTest passes.
  • The two previously ignored e2e tests listed above.

Summary by CodeRabbit

  • Bug Fixes

    • Removed users’ read-state entries when they leave or are removed from a channel.
    • Prevented removed members from continuing to appear as channel readers.
    • Preserved read states for remaining channel members.
  • Tests

    • Added coverage for member removal and read-state cleanup.
    • Re-enabled end-to-end tests for message and thread read-status updates after member removal.

@andremion andremion added the pr:bug Bug fix label Jul 20, 2026
@andremion

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Member removal now clears the removed user’s channel read state across direct channel updates, current event handling, and legacy event handling. Unit tests cover state cleanup and preservation of other readers, while two end-to-end read-decrement tests are enabled.

Changes

Member read-state cleanup

Layer / File(s) Summary
Read-state removal primitives
stream-chat-android-client/src/main/java/.../state/channel/internal/*, stream-chat-android-client/src/main/java/.../legacy/ChannelStateLogic.kt
Current and legacy channel state implementations can remove a user’s stored read state, with the legacy operation exposed through ChannelStateLogic.
Member-removal read cleanup
stream-chat-android-client/src/main/java/.../extensions/internal/Channel.kt, stream-chat-android-client/src/main/java/.../channel/internal/*
Direct member removal filters the member’s read entry, and both event-handler paths clear read state for removed members.
Read-state cleanup validation
stream-chat-android-client/src/test/java/.../*, stream-chat-android-compose-sample/src/androidTestE2eDebug/.../MessageDeliveryStatusTests.kt
Tests verify removal, preservation of other readers, no-op behavior, event handling, and enabled end-to-end read-decrement scenarios.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MemberRemovedEvent
  participant ChannelEventHandlerImpl
  participant ChannelStateImpl
  MemberRemovedEvent->>ChannelEventHandlerImpl: handle member removal
  ChannelEventHandlerImpl->>ChannelStateImpl: removeRead(userId)
  ChannelStateImpl->>ChannelStateImpl: remove userId from _reads
Loading

Suggested labels: released, pr:test

Suggested reviewers: gpunto, velikovpetar

Poem

A bunny hops through channels bright,
And clears old reads from member sight.
One reader gone, the rest remain,
Fresh state flows like springtime rain.
Tests now dance—hip-hop, hooray! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: updating read status when a reading member is removed.
Description check ✅ Passed The description covers Goal, Implementation, and Testing with concrete details and relevant acceptance tests.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch andrerego/and-1310-compose-message-read-status-is-not-updated-when-the-reading

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.95 MB 5.95 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.21 MB 11.21 MB 0.00 MB 🟢
stream-chat-android-compose 12.69 MB 12.69 MB 0.00 MB 🟢

@andremion
andremion marked this pull request as ready for review July 20, 2026 13:28
@andremion
andremion requested a review from a team as a code owner July 20, 2026 13:28
@andremion
andremion enabled auto-merge (squash) July 21, 2026 09:12
auto-merge was automatically disabled July 23, 2026 07:58

Head branch was modified

@andremion
andremion enabled auto-merge (squash) July 23, 2026 08:03
@andremion
andremion force-pushed the andrerego/and-1310-compose-message-read-status-is-not-updated-when-the-reading branch from 6929913 to e3321af Compare July 23, 2026 08:21
@sonarqubecloud

Copy link
Copy Markdown

@andremion
andremion merged commit 6afc75d into develop Jul 23, 2026
19 checks passed
@andremion
andremion deleted the andrerego/and-1310-compose-message-read-status-is-not-updated-when-the-reading branch July 23, 2026 08:58
andremion added a commit that referenced this pull request Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants