Skip to content

feat(ui): add configurable StreamBackButton unread count#2816

Open
VelikovPetar wants to merge 1 commit into
masterfrom
feature/FLU-557_fix_back_button_unread_counts
Open

feat(ui): add configurable StreamBackButton unread count#2816
VelikovPetar wants to merge 1 commit into
masterfrom
feature/FLU-557_fix_back_button_unread_counts

Conversation

@VelikovPetar

@VelikovPetar VelikovPetar commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Submit a pull request

Linear: FLU-557

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

The StreamChannelHeader back-button unread badge counted the currently open channel in its total, so it never reflected "unread elsewhere".

  • StreamBackButton now takes an unreadCount configuration via the new StreamBackButtonUnreadCount:
    • .total({excludeCid}) — total unread across channels, optionally excluding one channel.
    • .channel(cid) — a specific channel's unread count.
  • StreamChannelHeader now uses .total(excludeCid: channel.cid), so its back-button badge shows the unread messages waiting in other channels.
  • StreamUnreadIndicator gained an opt-in excludeCid (bare usage is unchanged).
  • showUnreadCount and channelId on StreamBackButton are deprecated but still functional — fully backwards compatible.

Test instructions: open a channel that has unread messages while other channels also have unread. The header back-button badge shows total − thisChannel; going back to the channel list, the badge shows the full total. Covered by unit tests in back_button_test.dart and unread_indicator_test.dart (incl. the deprecated paths).

Screenshots / Videos

Before After
unreads-before.mov
unreads-after.mov

Summary by CodeRabbit

  • New Features

    • Added flexible unread badge configuration for back buttons, supporting total unread counts or counts for a specific channel.
    • Channel headers now exclude the currently open channel from total unread badges.
  • Bug Fixes

    • Corrected unread badge totals and prevented negative counts when excluding the active channel.
  • Documentation

    • Added migration guidance and examples for the updated back-button configuration.
    • Deprecated older unread badge options in favor of the new configuration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

StreamBackButton now accepts typed unread-count configurations, supports excluding the current channel from totals, updates channel and thread headers, preserves deprecated flags, and adds coverage and migration documentation.

Changes

Unread badge migration

Layer / File(s) Summary
Excluded total unread calculation
packages/stream_chat_flutter/lib/src/indicators/unread_indicator.dart, packages/stream_chat_flutter/test/src/indicators/unread_indicator_test.dart
StreamUnreadIndicator subtracts an optional channel count from total unread values, clamps negative results to zero, and handles missing channels.
Typed back-button unread API
packages/stream_chat_flutter/lib/src/misc/back_button.dart, packages/stream_chat_flutter/test/src/misc/back_button_test.dart
StreamBackButtonUnreadCount supports total and channel modes; deprecated flags remain supported, and unread-count behavior is covered across configurations.
Header and example integrations
packages/stream_chat_flutter/lib/src/channel/channel_header.dart, packages/stream_chat_flutter/lib/src/misc/thread_header.dart, packages/stream_chat_flutter/example/lib/main.dart, packages/stream_chat_flutter/test/src/channel/channel_header_test.dart, docs/docs_screenshots/test/localization/localization_rtl_test.dart
Headers and the example pass explicit unread-count modes, including exclusion of the active channel in the default channel header.
Migration and release documentation
migrations/redesign/headers_and_icons.md, packages/stream_chat_flutter/CHANGELOG.md
Documentation describes the new API, deprecated parameters, and current-channel exclusion behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Header
  participant StreamBackButton
  participant StreamUnreadIndicator
  participant ClientState
  Header->>StreamBackButton: configure unreadCount
  StreamBackButton->>StreamUnreadIndicator: select total or channel mode
  StreamUnreadIndicator->>ClientState: read unread streams
  ClientState-->>StreamUnreadIndicator: provide unread counts
  StreamUnreadIndicator-->>StreamBackButton: render badge
Loading

Suggested reviewers: xsahil03x

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: configurable unread-count behavior for StreamBackButton.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/FLU-557_fix_back_button_unread_counts

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.

@VelikovPetar VelikovPetar changed the title feat(ui): add configurable StreamBackButton unread count feat(ui): add configurable StreamBackButton unread count Jul 14, 2026
///
/// Set [excludeCid] to omit a channel's unread messages from the total -
/// for example, the currently open channel.
const factory StreamBackButtonUnreadCount.total({String? excludeCid}) = _TotalUnreadCount;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not completely sure about the naming here, let me know if you think we should use something different (.unreadMessages()perhaps, to serve as a forecast for the potentially upcoming .unreadChannels())

@VelikovPetar VelikovPetar marked this pull request as ready for review July 14, 2026 19:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/stream_chat_flutter/example/lib/main.dart`:
- Around line 228-232: Update the unread-count selection in the back-button
setup to use the total count excluding the current channel rather than
StreamBackButtonUnreadCount.channel(cid). Preserve the existing fallback
behavior when no channel CID is available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4e9d622-7b75-4baf-801c-03086903330e

📥 Commits

Reviewing files that changed from the base of the PR and between 5c4c5a7 and a1f86e7.

📒 Files selected for processing (11)
  • docs/docs_screenshots/test/localization/localization_rtl_test.dart
  • migrations/redesign/headers_and_icons.md
  • packages/stream_chat_flutter/CHANGELOG.md
  • packages/stream_chat_flutter/example/lib/main.dart
  • packages/stream_chat_flutter/lib/src/channel/channel_header.dart
  • packages/stream_chat_flutter/lib/src/indicators/unread_indicator.dart
  • packages/stream_chat_flutter/lib/src/misc/back_button.dart
  • packages/stream_chat_flutter/lib/src/misc/thread_header.dart
  • packages/stream_chat_flutter/test/src/channel/channel_header_test.dart
  • packages/stream_chat_flutter/test/src/indicators/unread_indicator_test.dart
  • packages/stream_chat_flutter/test/src/misc/back_button_test.dart

Comment on lines +228 to +232
// Show the current channel's own unread count on the back button.
final unreadCount = switch (StreamChannel.of(context).channel.cid) {
final cid? => StreamBackButtonUnreadCount.channel(cid),
_ => const StreamBackButtonUnreadCount.total(),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Show the total unread count excluding the current channel.

Configuring the back button to show the current channel's unread count (.channel(cid)) results in a suboptimal UX, as the count will typically be 0 while the user is actively viewing the channel.

Since navigating back from the ChannelPage takes the user to the channel list, it's generally preferable to show the total unread count excluding the current channel. This also accurately demonstrates the new default behavior of StreamChannelHeader introduced in this PR.

💡 Proposed fix
-    // Show the current channel's own unread count on the back button.
-    final unreadCount = switch (StreamChannel.of(context).channel.cid) {
-      final cid? => StreamBackButtonUnreadCount.channel(cid),
-      _ => const StreamBackButtonUnreadCount.total(),
-    };
+    // Show the total unread count across other channels on the back button.
+    final unreadCount = StreamBackButtonUnreadCount.total(
+      excludeCid: StreamChannel.of(context).channel.cid,
+    );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Show the current channel's own unread count on the back button.
final unreadCount = switch (StreamChannel.of(context).channel.cid) {
final cid? => StreamBackButtonUnreadCount.channel(cid),
_ => const StreamBackButtonUnreadCount.total(),
};
// Show the total unread count across other channels on the back button.
final unreadCount = StreamBackButtonUnreadCount.total(
excludeCid: StreamChannel.of(context).channel.cid,
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stream_chat_flutter/example/lib/main.dart` around lines 228 - 232,
Update the unread-count selection in the back-button setup to use the total
count excluding the current channel rather than
StreamBackButtonUnreadCount.channel(cid). Preserve the existing fallback
behavior when no channel CID is available.

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 71.30%. Comparing base (5c4c5a7) to head (a1f86e7).

Files with missing lines Patch % Lines
...t_flutter/lib/src/indicators/unread_indicator.dart 92.85% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2816      +/-   ##
==========================================
+ Coverage   71.28%   71.30%   +0.02%     
==========================================
  Files         430      430              
  Lines       26930    26951      +21     
==========================================
+ Hits        19196    19217      +21     
  Misses       7734     7734              

☔ 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.

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.

1 participant