Skip to content

fix(llc): keep Channel.memberCount fresh from channel events, make primitive value streams distinct - #2936

Merged
xsahil03x merged 2 commits into
v9from
port/master-to-v9/member-count-and-distinct-streams
Sep 3, 2026
Merged

fix(llc): keep Channel.memberCount fresh from channel events, make primitive value streams distinct#2936
xsahil03x merged 2 commits into
v9from
port/master-to-v9/member-count-and-distinct-streams

Conversation

@xsahil03x

@xsahil03x xsahil03x commented Sep 3, 2026

Copy link
Copy Markdown
Member

Submit a pull request

Linear: FLU-

Github Issue: #

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

Backports two llc changes from master to v9, one commit each. They are ordered: the second rewrites the memberCountStream test the first adds.


1. Keep Channel.memberCount fresh from channel events

Backport of 9610ce2 (originally #2933).

Channel.memberCount / memberCountStream only ever reflected the member_count returned by query / watch and channel.updated. The member.added / member.removed handlers update the loaded member list but leave the count untouched, so it went stale for the rest of the session as soon as anyone joined or left. The handlers are byte-for-byte identical from 3.0.0 onwards, so this is not a regression.

The backend already ships the authoritative count as channel_member_count event metadata on channel events, next to the channel_message_count we already consume. This adds Event.channelMemberCount, applies it to ChannelModel.memberCount, and folds both counters into a single _listenChannelCounts listener so an event carrying both produces one state update.

Port notes

  • event.g.dart hand-edited, not regenerated. Master's generated output uses Dart 3.10 null-aware map elements ('key': ?instance.x), which v9's sdk: ^3.6.2 rejects. The two added lines follow v9's existing if (instance.x case final value?) form, matching the adjacent channel_message_count entry.
  • Formatting. Master formats at 120 cols, v9 at the 80-col default, so the ported test hunks were rewrapped.
  • Serialization tests. Master's commit did not touch event_test.dart / test/fixtures/event.json. Extended here for channel_member_count, following what fix(llc): update watcher count from realtime events and ignore events after dispose #2898 did for watcher_count on this branch.

2. Make primitive value streams distinct

Backport of 5dce4c9 (originally #2935).

Channel and ClientState getters that map to a single primitive value emitted on every channel-state / current-user update, even when the value was unchanged — pushing four distinct message counts through messageCountStream produced 13 emissions, and memberCountStream fired on every new message.

Those getters now .distinct(), matching the stream getters in channel.dart that already do (ownCapabilitiesStream, messagesStream, draftStream, …). Scope is primitives only (bool, int, String?, DateTime?); model and collection streams are untouched. All 19 call sites from the master change are present on v9 and were ported.

Port notes

  • Master drops a redundant distinct() in stream_message_composer.dart, which does not exist on v9. The equivalent line lives in stream_message_input.dart:615 and covers the same two-arm switch; verified that both ChannelClientState.draftStream and threadDraftStream already dedupe on v9, so dropping it is a no-op here too.
  • Master's changelog bullet for the Dart SDK floor raise is master-only and was not brought over.

Verification

  • melos run format — clean (0 changed).
  • melos run analyze — no issues in any package.
  • stream_chat: 1333 pass, 2 skipped, 0 fail.
  • stream_chat_flutter_core: 231 pass.
  • stream_chat_flutter (CI=true): 824 pass, 20 fail — all golden variants in avatars/gradient_avatar_test.dart, pre-existing local-vs-CI rendering drift unrelated to these changes.

Screenshots / Videos

No UI changes.

renefloor and others added 2 commits September 3, 2026 15:24
`Channel.memberCount` / `memberCountStream` only ever reflected the
`member_count` returned by `query` / `watch` and `channel.updated`. The
`member.added` / `member.removed` handlers update the loaded member list
but leave the count untouched, so it went stale for the rest of the
session as soon as anyone joined or left.

The backend already ships the authoritative count as `channel_member_count`
event metadata on channel events, next to the `channel_message_count` we
already consume. Parse it into `Event.channelMemberCount` and apply it to
the channel state, folding both counters into a single listener so one
event produces one state update.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 9610ce2)
Channel and ClientState getters that map to a single primitive value now
dedupe, so listeners only wake up when the value actually changes rather
than on every channel state or current user update.

The message input's redundant `distinct()` on the draft stream is dropped,
as `ChannelClientState.draftStream` and `threadDraftStream` already dedupe.

Port of #2935 from master.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 6ded030f-adfd-4395-94a9-19641d033ebf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 26.53061% with 36 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (v9@ec0963b). Learn more about missing BASE report.

Files with missing lines Patch % Lines
packages/stream_chat/lib/src/client/channel.dart 29.26% 29 Missing ⚠️
packages/stream_chat/lib/src/client/client.dart 0.00% 6 Missing ⚠️
...er/lib/src/message_input/stream_message_input.dart 0.00% 1 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##             v9    #2936   +/-   ##
=====================================
  Coverage      ?   67.41%           
=====================================
  Files         ?      431           
  Lines         ?    27444           
  Branches      ?        0           
=====================================
  Hits          ?    18500           
  Misses        ?     8944           
  Partials      ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xsahil03x
xsahil03x merged commit 9355600 into v9 Sep 3, 2026
26 checks passed
@xsahil03x
xsahil03x deleted the port/master-to-v9/member-count-and-distinct-streams branch September 3, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants