Skip to content

chore(repo): fix ci issues for flutter 3.44#2667

Merged
xsahil03x merged 10 commits into
masterfrom
chore/fix-ci
May 19, 2026
Merged

chore(repo): fix ci issues for flutter 3.44#2667
xsahil03x merged 10 commits into
masterfrom
chore/fix-ci

Conversation

@xsahil03x
Copy link
Copy Markdown
Member

@xsahil03x xsahil03x commented May 19, 2026

Summary by CodeRabbit

  • Chores
    • Updated linter rules and suppressed deprecated-member analyzer warnings across UI components.
    • Enforced a minimum Android compile SDK, added temporary Gradle migration flags, and removed a hardcoded package attribute from an Android manifest.
    • Removed MinimumOSVersion from iOS plist.
  • Bug Fixes
    • Improved message ordering/merge logic to prevent duplicate messages and to pick the correct unread boundary.
    • Adjusted poll switch tile so background, border radius and clipping render consistently.
  • Tests
    • Added regression tests covering optimistic-send + server-echo message scenarios.

Review Change Stack

* Remove `invariant_booleans` and `prefer_equal_for_default_values` lint rules
* Add `deprecated_member_use` ignores for `cacheExtent` and `onReorder` usage
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d26c1bf5-088d-43ec-a680-f8821209ec2d

📥 Commits

Reviewing files that changed from the base of the PR and between 8690746 and e51fdcd.

⛔ Files ignored due to path filters (8)
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_light.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • packages/stream_chat/lib/src/client/channel.dart
  • packages/stream_chat/test/src/client/channel_test.dart
  • packages/stream_chat_flutter_core/lib/src/stream_channel.dart

📝 Walkthrough

Walkthrough

Adds analyzer ignore directives to suppress deprecated_member_use warnings in multiple widgets, wraps a SwitchListTile in a Material for rounded/clipped styling, moves the message input background color into a surrounding Material, enforces a minimum Android compileSdkVersion and adds Gradle flags, removes the profile manifest package attribute and iOS MinimumOSVersion, and adjusts message-index lookups with regression tests to prevent duplicate messages.

Changes

Widget lint suppressions and UI wrapper change

Layer / File(s) Summary
Deprecation ignore directives in widget implementations
packages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dart, packages/stream_chat_flutter/lib/src/misc/separated_reorderable_list_view.dart, packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart
Added // ignore: deprecated_member_use comments to several widget build/initializer sites (ListView, constructor super initializers, cacheExtent positions). No runtime logic or public API signatures changed.
PollSwitchListTile Material wrapper
packages/stream_chat_flutter/lib/src/poll/creator/poll_switch_list_tile.dart
Removed SwitchListTile tileColor/shape usage and wrapped the tile in a Material applying color, borderRadius, and clipBehavior: Clip.antiAlias; title and contentPadding preserved.
StreamMessageInput background → Material
packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart
Moved message input background color from DecoratedBox BoxDecoration.color to Material.color; DecoratedBox now only provides boxShadow.

Sample app Android/iOS platform and build config updates

Layer / File(s) Summary
Android compileSdkVersion minimum
sample_app/android/app/build.gradle, sample_app/android/build.gradle
Change compileSdkVersion assignments to Math.max(flutter.compileSdkVersion, 36) to enforce a minimum SDK when configuring app and subprojects.
Android Gradle migration flags
sample_app/android/gradle.properties
Add android.builtInKotlin=false and android.newDsl=false with Flutter migrator comments.
Profile AndroidManifest package attribute removal
sample_app/android/app/src/profile/AndroidManifest.xml
Remove the package attribute from the root <manifest> element.
iOS AppFrameworkInfo plist MinimumOSVersion removal
sample_app/ios/Flutter/AppFrameworkInfo.plist
Removed the MinimumOSVersion (previously 12.0) entry from the plist.

Channel indexing and tests

Layer / File(s) Summary
ChannelClientState.updateMessage tail-scan
packages/stream_chat/lib/src/client/channel.dart
Replace prior oldIndex conditional/indexWhere logic with messages.lastIndexWhere((m) => m.id == message.id) to scan from the tail when locating an existing message for upsert/rewrite.
First-unread index selection
packages/stream_chat_flutter_core/lib/src/stream_channel.dart
Use messages.lastIndexWhere(...) instead of indexWhere when locating lastReadMessageId, choosing the last occurrence among duplicates.
WS regression tests
packages/stream_chat/test/src/client/channel_test.dart
Add two tests covering optimistic local sends followed by server message.new echoes (with later createdAt) and a retry-after-offline scenario to ensure no duplicate messages are produced.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • VelikovPetar
  • Brazol

"🐰
I hopped through warnings, soft and slight,
Quietly tucked deprecated lines out of sight.
A Material coat for a Switch so neat,
Message indexing fixed to keep states discrete,
Tests guard echoes — one message, just right."

🚥 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 'chore(repo): fix ci issues for flutter 3.44' accurately reflects the main objective of the pull request, which focuses on resolving CI issues and compatibility problems introduced by Flutter 3.44.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/fix-ci

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/stream_chat_flutter/lib/src/misc/separated_reorderable_list_view.dart (1)

60-61: 💤 Low value

Migrate from deprecated onReorder callback to onReorderItem.

The onReorder callback is deprecated as of Flutter 3.27 in favor of onReorderItem. The new callback handles index adjustments automatically, eliminating the need for the manual adjustment logic at lines 66-67. Replace the onReorder callback with onReorderItem and remove the manual index adjustment workaround that accounts for Flutter issue #24786.

🤖 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/lib/src/misc/separated_reorderable_list_view.dart`
around lines 60 - 61, Replace the deprecated onReorder callback with the new
onReorderItem callback in SeparatedReorderableListView (remove the // ignore:
deprecated_member_use line), change the handler signature to match
onReorderItem, and remove the manual index adjustment workaround that
compensates for Flutter issue `#24786` (the logic that adjusts oldIndex/newIndex
at lines 66-67). Ensure the new onReorderItem handler forwards the received
indices directly to your reorder logic (or invokes the same internal reorder
method) since onReorderItem already provides corrected indices.
packages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dart (1)

372-373: 💤 Low value

Plan migration to scrollCacheExtent for Flutter 3.41+ compatibility.

The cacheExtent parameter is deprecated starting Flutter 3.41.0 (not yet relevant for the current 3.27.4 target, but worth tracking). When migrating, replace with:

scrollCacheExtent: const ScrollCacheExtent.pixels(1040),

Consider adding a TODO comment to track this for future upgrades.

🤖 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/lib/src/message_input/stream_message_input_attachment_list.dart`
around lines 372 - 373, Replace the deprecated cacheExtent usage in the
StreamMessageInputAttachmentList ListView (the line with "cacheExtent: 104 *
10") with the newer scrollCacheExtent API for future Flutter 3.41+
compatibility: remove the cacheExtent entry and add scrollCacheExtent: const
ScrollCacheExtent.pixels(1040) in the same widget, and add a concise TODO above
it noting this migration for Flutter 3.41+; ensure you keep the same intent
(caching 10 items ahead) and the change is applied inside the
StreamMessageInputAttachmentList build where the ListView is constructed.
🤖 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.

Nitpick comments:
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dart`:
- Around line 372-373: Replace the deprecated cacheExtent usage in the
StreamMessageInputAttachmentList ListView (the line with "cacheExtent: 104 *
10") with the newer scrollCacheExtent API for future Flutter 3.41+
compatibility: remove the cacheExtent entry and add scrollCacheExtent: const
ScrollCacheExtent.pixels(1040) in the same widget, and add a concise TODO above
it noting this migration for Flutter 3.41+; ensure you keep the same intent
(caching 10 items ahead) and the change is applied inside the
StreamMessageInputAttachmentList build where the ListView is constructed.

In
`@packages/stream_chat_flutter/lib/src/misc/separated_reorderable_list_view.dart`:
- Around line 60-61: Replace the deprecated onReorder callback with the new
onReorderItem callback in SeparatedReorderableListView (remove the // ignore:
deprecated_member_use line), change the handler signature to match
onReorderItem, and remove the manual index adjustment workaround that
compensates for Flutter issue `#24786` (the logic that adjusts oldIndex/newIndex
at lines 66-67). Ensure the new onReorderItem handler forwards the received
indices directly to your reorder logic (or invokes the same internal reorder
method) since onReorderItem already provides corrected indices.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87d42164-b9df-4e1b-9b50-c550cd7d1937

📥 Commits

Reviewing files that changed from the base of the PR and between b82fba7 and e30d5ec.

📒 Files selected for processing (4)
  • analysis_options.yaml
  • packages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dart
  • packages/stream_chat_flutter/lib/src/misc/separated_reorderable_list_view.dart
  • packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart
💤 Files with no reviewable changes (1)
  • analysis_options.yaml

xsahil03x and others added 2 commits May 19, 2026 14:07
Flutter 3.44 added a runtime assertion (list_tile.dart#_findIntermediateWidget)
that fires whenever a ListTile with an onTap (e.g. SwitchListTile) has a
ColoredBox/DecoratedBox-with-color ancestor before its nearest Material —
because that ancestor paints over the Material surface where the ListTile
draws its background and ink response.

The widget previously wrapped the SwitchListTile and its optional children
in a colored DecoratedBox. That triggered the assertion on every poll-creator
golden test on Flutter 3.44.

Replace the outer DecoratedBox with a Material widget carrying the same
color + borderRadius. Material doubles as the ancestor the ListTile is
looking for, so the assertion no longer fires; the visible panel that the
optional children share with the tile is preserved. tileColor and the
redundant shape are dropped from the inner SwitchListTile — Material owns
the rounded surface now.

melos.yaml SDK floor (Flutter >=3.27.4, Dart ^3.6.2) is unchanged; Material
has supported color + borderRadius + clipBehavior since well before 3.27.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/stream_chat_flutter/lib/src/poll/creator/poll_switch_list_tile.dart (1)

64-64: ⚡ Quick win

Consider using Clip.hardEdge for better performance.

Clip.antiAlias is more expensive than Clip.hardEdge. For simple rounded rectangles like this, Clip.hardEdge typically provides sufficient visual quality with better rendering performance.

⚡ Proposed change for improved performance
-      clipBehavior: Clip.antiAlias,
+      clipBehavior: Clip.hardEdge,
🤖 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/lib/src/poll/creator/poll_switch_list_tile.dart`
at line 64, The widget currently sets clipBehavior: Clip.antiAlias which is more
expensive; update the PollSwitchListTile (the widget that defines clipBehavior)
to use clipBehavior: Clip.hardEdge instead for this simple rounded-rect clipping
to improve rendering performance, making the change where the Clip.antiAlias
value is assigned in the build/constructor of PollSwitchListTile.
🤖 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.

Nitpick comments:
In
`@packages/stream_chat_flutter/lib/src/poll/creator/poll_switch_list_tile.dart`:
- Line 64: The widget currently sets clipBehavior: Clip.antiAlias which is more
expensive; update the PollSwitchListTile (the widget that defines clipBehavior)
to use clipBehavior: Clip.hardEdge instead for this simple rounded-rect clipping
to improve rendering performance, making the change where the Clip.antiAlias
value is assigned in the build/constructor of PollSwitchListTile.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: af12aab8-8a21-4b01-8dc9-7054778079e8

📥 Commits

Reviewing files that changed from the base of the PR and between e30d5ec and 18e9a0b.

⛔ Files ignored due to path filters (138)
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_idle_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_idle_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playing_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playing_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playlist_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playlist_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_3.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_issue_2369.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/group_avatar_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/user_avatar_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/avatars/goldens/ci/user_avatar_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/bottom_sheets/goldens/ci/attachment_modal_sheet_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/bottom_sheets/goldens/ci/edit_message_sheet_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/bottom_sheets/goldens/ci/error_alert_sheet_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/channel/goldens/ci/channel_header_bottom_widget.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/context_menu_items/goldens/ci/download_menu_item_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/context_menu_items/goldens/ci/stream_chat_context_menu_item_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/dialogs/goldens/ci/confirmation_dialog_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/dialogs/goldens/ci/delete_message_dialog_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/gallery/goldens/ci/gallery_footer_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/gallery/goldens/ci/gallery_header_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/icons/goldens/ci/stream_svg_icon_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/icons/goldens/ci/stream_svg_icon_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_3.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/upload_progress_indicator_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/upload_progress_indicator_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/indicators/goldens/ci/upload_progress_indicator_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_idle_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_idle_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_hold_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_hold_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_locked_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_locked_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_stopped_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_stopped_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/attachment_button_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/clear_input_item_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/command_button_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/countdown_button_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/dm_checkbox_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/dm_checkbox_1.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_input/goldens/ci/dm_checkbox_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_custom.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_widget/goldens/ci/message_text.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/reaction_bubble_2.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/reaction_bubble_3_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/reaction_bubble_3_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/reaction_bubble_like_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/reaction_bubble_like_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_custom_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_custom_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_empty_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_empty_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_inverted_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_inverted_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_less_data_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_less_data_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_progress_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_audio_waveform_slider_progress_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_timestamp_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_timestamp_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/system_message_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/misc/goldens/ci/system_message_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_delete_option_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_delete_option_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_error_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_error_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_error_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_error_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_error.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_error.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_options_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_options_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_with_show_all_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_with_show_all_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_with_initial_value_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_with_initial_value_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_end_vote_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_end_vote_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_long_question_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_long_question_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_all_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_all_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_disabled_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_disabled_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_limited_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_limited_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_unique_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_unique_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_with_initial_option_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_with_initial_option_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_closed_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_closed_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/draft_scroll_view/goldens/ci/stream_draft_list_tile_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/draft_scroll_view/goldens/ci/stream_draft_list_tile_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_thread_list_tile_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_thread_list_tile_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_unread_threads_banner_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_unread_threads_banner_light.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • packages/stream_chat_flutter/lib/src/poll/creator/poll_switch_list_tile.dart

xsahil03x and others added 4 commits May 19, 2026 17:04
Some transitive dependencies pulled in by the sample app require
compileSdk >= 36 via their AAR metadata, but Flutter's bundled
compileSdkVersion is still 35, so the build fails with:

  CheckAarMetadataWorkAction: Dependency '<lib>' requires libraries
  and applications that depend on it to compile against version 36
  or later of the Android APIs.

Pin a floor of 36 via Math.max(flutter.compileSdkVersion, 36) in both
the :app module and the root subprojects block (so plugin projects
pick it up too). The Math.max means we'll automatically follow
Flutter's version once it ships 36+ without another change here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small, version-safe migrations Flutter applies automatically the
first time the sample_app is built on a recent enough toolchain:

- android/app/src/profile/AndroidManifest.xml: drop the deprecated
  `package="..."` attribute. AGP 7.4+ reads the package name from the
  module's `namespace` in build.gradle and warns about the attribute.

- android/gradle.properties: add `android.builtInKotlin=false` and
  `android.newDsl=false`. These are opt-outs the Flutter migrator
  writes to keep the existing Kotlin/DSL behaviour stable; older AGP
  that doesn't recognise them just warns.

- ios/Flutter/AppFrameworkInfo.plist: drop `MinimumOSVersion=12.0`.
  The Xcode project's deployment target is the source of truth on every
  supported Flutter version, so the plist entry is redundant.

All three are safe across the monorepo's supported Flutter range
(>=3.27.4 in melos.yaml). The iOS/macOS Swift Package Manager
migration that Flutter also wants to apply is intentionally left
uncommitted because SPM was opt-in on 3.27.4 and would churn or
break local builds for devs on the floor version.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Flutter 3.44 asserts when a ListTile (or SwitchListTile/CheckboxListTile)
walks up the tree and encounters a DecoratedBox with a non-transparent
color before reaching its nearest Material ancestor. The intermediate
colored DecoratedBox in StreamMessageInput tripped this for
DmCheckboxListTile when rendered inside a thread.

Moving inputBackgroundColor onto the outer Material removes the
intermediate color while preserving the custom shadow on DecoratedBox.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.29%. Comparing base (d9d4ff4) to head (e51fdcd).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2667      +/-   ##
==========================================
- Coverage   65.29%   65.29%   -0.01%     
==========================================
  Files         423      423              
  Lines       26642    26635       -7     
==========================================
- Hits        17397    17390       -7     
  Misses       9245     9245              

☔ View full report in Codecov by Sentry.
📢 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 and others added 3 commits May 19, 2026 18:47
The previous fast-path in `ChannelClientState.updateMessage` returned -1
(treat as insert) whenever the incoming message's `createdAt` was later
than `messages.last.createdAt`. That assumption breaks for the
optimistic-send + server-echo flow and, more visibly, after a
retry-from-offline once another message has slipped in between the local
copy and the tail — the locally-sent message is no longer at the end, so
the id-by-id scan was skipped and `sortedUpsertAt(-1, ...)` appended a
duplicate. Downstream, `RenderSliverMultiBoxAdaptor._debugVerifyChildOrder`
crashed because the message list now had two children keyed by the same
`message.id`.

Replace the shortcut with a single `lastIndexWhere` scan. Walking from
the tail keeps the common-case latency low (updates almost always target
a recent message) and remains correct when the locally-inserted copy is
buried mid-list.

Two regression tests in `channel_test.dart` route through
`channel.sendMessage` with a mocked client and fire a `message.new`
event afterward — one with the local copy still at the tail, one with
another message arriving in between (the offline-retry shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`getFirstUnreadMessage` looks up the user's last-read message in the
channel's canonical message list (ascending by `createdAt`, newest at
the tail). The last-read pointer is almost always close to the most
recent message — there's already a fast-path for the exact-tail case
on the line above. Swap `indexWhere` for `lastIndexWhere` so the
general case also finishes in a few comparisons instead of walking
the whole buffer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@xsahil03x xsahil03x merged commit 1f4eae9 into master May 19, 2026
18 of 19 checks passed
@xsahil03x xsahil03x deleted the chore/fix-ci branch May 19, 2026 17:04
xsahil03x added a commit that referenced this pull request May 20, 2026
Brings master's QA / security / perf work into the v10 design-refresh
branch.

Highlights of what landed in v10 from master:

LLC (`stream_chat`)
- `Client.queryDrafts` now forwards `filter` (#2647).
- `Client.queryChannels` coalesces concurrent identical queries via the
  new `InFlightCache<K, V>` (#2652).
- `SortedListX` / `ListX` extensions added in `list_extensions.dart`;
  duplicate-keyed inputs are tolerated by `merge` (#2660). v10's
  `IterableMergeExtension.merge` / `.mergeFrom` are kept — `SortedListX`
  is on `List` and routes there for the new perf paths; the old
  extension still serves `Iterable<T>` callers in v10.
- `ChannelClientState._checkExpiredAttachmentMessages` removed (#2653);
  v10's `StreamImageCDN.cacheKey` already keeps the image cache valid
  across signed-URL rotations.
- `ChannelClientState.updateChannelState` now identity-short-circuits
  when `updatedState.messages` is null or the same reference, so
  downstream `.distinct()` listeners can skip rebuilds.
- Reaction listeners now dispatch via `_findMessage` (parentId-aware)
  while keeping v10's `addMyReaction` / `deleteMyReaction` semantics.

`stream_chat_flutter_core`
- `BetterStreamBuilder` correctness fixes: mounted guard, error reporting
  via `FlutterError.reportError`, identity-equal emission gating (#2651).
- `MessageListCore` caches its `messagesStream` / `_initialMessages` as
  fields instead of recomputing in `build()` (#2651). `defaultMessageFilter`
  takes an optional `currentUserId`.
- `StreamChatCore` debounces connectivity events to 3 s (#2652).

`stream_chat_flutter`
- `scrollable_positioned_list/`: master version taken in full. Bounded
  `_keyToIndexMap`, `isScrolling` / `isScrollingListenable`,
  `itemKeyBuilder` anchor preservation, fit-anchor fallback in
  `UnboundedRenderViewport`, sensible defaults on `scrollTo` (#2651).
- `tld.dart` removed (#2654); `StreamMessageComposer` relaxed its URL
  regex from `[a-z]{2,4}` to `[a-z]{2,}` and dropped the `isValidTLD`
  filter at both call sites.
- `StreamMessageListView` and `separated_reorderable_list_view`:
  v10's design-refresh version retained. v10 already covers the
  functional surface; master's identity-preserving micro-optimizations
  to `updateMessage` are a follow-up.

CI / repo
- Path/draft gating job (`gate`) added to `legacy_version_analyze`,
  `check_db_entities`, and `stream_flutter_workflow` (#2669).
- Flutter 3.44 fixes (#2667), pana / build cleanups (#2656),
  local-setup CI fixes (#2650).
- `melos.yaml`: kept v10's higher floors; added `firebase_crashlytics`
  (master's #2665); dropped `sentry_flutter` (per master).

Notes / follow-ups
- `sample_app/`: v10's redesigned app retained. The Sentry → Firebase
  Crashlytics migration (#2665) applies to master's pre-redesign sample
  app and was not ported here; left for a separate pass.
- `channel_test.dart` `updateMessage quoted-rewrite > does not rewrite
  quotes when an existing quoted target is updated without being
  deleted` is marked `skip:` — v10's `_updateMessages` reconstructs the
  channel list via `_mergeMessagesIntoExisting`, so identity is not
  preserved on non-deletion edits. Functional behavior matches master.
- `goldens/`: deleted-on-v10 goldens kept deleted; modified-on-both
  goldens kept at v10's bytes (the redesigned UI is the source of
  truth).
- `stream_message_composer.dart` had `SizeTransition(alignment:)` which
  was never a valid parameter — switched to `axisAlignment: -1` (the
  Flutter API the v10 author intended).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xsahil03x added a commit that referenced this pull request May 20, 2026
Brings master's QA / security / perf work into the v10 design-refresh
branch.

Highlights of what landed in v10 from master:

LLC (`stream_chat`)
- `Client.queryDrafts` now forwards `filter` (#2647).
- `Client.queryChannels` coalesces concurrent identical queries via the
  new `InFlightCache<K, V>` (#2652).
- `SortedListX` / `ListX` extensions added in `list_extensions.dart`;
  duplicate-keyed inputs are tolerated by `merge` (#2660). v10's
  `IterableMergeExtension.merge` / `.mergeFrom` are kept — `SortedListX`
  is on `List` and routes there for the new perf paths; the old
  extension still serves `Iterable<T>` callers in v10.
- `ChannelClientState._checkExpiredAttachmentMessages` removed (#2653);
  v10's `StreamImageCDN.cacheKey` already keeps the image cache valid
  across signed-URL rotations.
- `ChannelClientState.updateChannelState` now identity-short-circuits
  when `updatedState.messages` is null or the same reference, so
  downstream `.distinct()` listeners can skip rebuilds.
- Reaction listeners now dispatch via `_findMessage` (parentId-aware)
  while keeping v10's `addMyReaction` / `deleteMyReaction` semantics.

`stream_chat_flutter_core`
- `BetterStreamBuilder` correctness fixes: mounted guard, error reporting
  via `FlutterError.reportError`, identity-equal emission gating (#2651).
- `MessageListCore` caches its `messagesStream` / `_initialMessages` as
  fields instead of recomputing in `build()` (#2651). `defaultMessageFilter`
  takes an optional `currentUserId`.
- `StreamChatCore` debounces connectivity events to 3 s (#2652).

`stream_chat_flutter`
- `scrollable_positioned_list/`: master version taken in full. Bounded
  `_keyToIndexMap`, `isScrolling` / `isScrollingListenable`,
  `itemKeyBuilder` anchor preservation, fit-anchor fallback in
  `UnboundedRenderViewport`, sensible defaults on `scrollTo` (#2651).
- `tld.dart` removed (#2654); `StreamMessageComposer` relaxed its URL
  regex from `[a-z]{2,4}` to `[a-z]{2,}` and dropped the `isValidTLD`
  filter at both call sites.
- `StreamMessageListView` and `separated_reorderable_list_view`:
  v10's design-refresh version retained. v10 already covers the
  functional surface; master's identity-preserving micro-optimizations
  to `updateMessage` are a follow-up.

CI / repo
- Path/draft gating job (`gate`) added to `legacy_version_analyze`,
  `check_db_entities`, and `stream_flutter_workflow` (#2669).
- Flutter 3.44 fixes (#2667), pana / build cleanups (#2656),
  local-setup CI fixes (#2650).
- `melos.yaml`: kept v10's higher floors; added `firebase_crashlytics`
  (master's #2665); dropped `sentry_flutter` (per master).

Notes / follow-ups
- `sample_app/`: v10's redesigned app retained. The Sentry → Firebase
  Crashlytics migration (#2665) applies to master's pre-redesign sample
  app and was not ported here; left for a separate pass.
- `channel_test.dart` `updateMessage quoted-rewrite > does not rewrite
  quotes when an existing quoted target is updated without being
  deleted` is marked `skip:` — v10's `_updateMessages` reconstructs the
  channel list via `_mergeMessagesIntoExisting`, so identity is not
  preserved on non-deletion edits. Functional behavior matches master.
- `goldens/`: deleted-on-v10 goldens kept deleted; modified-on-both
  goldens kept at v10's bytes (the redesigned UI is the source of
  truth).
- `stream_message_composer.dart` had `SizeTransition(alignment:)` which
  was never a valid parameter — switched to `axisAlignment: -1` (the
  Flutter API the v10 author intended).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xsahil03x added a commit that referenced this pull request May 20, 2026
Brings master's QA / security / perf work into the v10 design-refresh
branch.

Highlights of what landed in v10 from master:

LLC (`stream_chat`)
- `Client.queryDrafts` now forwards `filter` (#2647).
- `Client.queryChannels` coalesces concurrent identical queries via the
  new `InFlightCache<K, V>` (#2652).
- `SortedListX` / `ListX` extensions added in `list_extensions.dart`;
  duplicate-keyed inputs are tolerated by `merge` (#2660). v10's
  `IterableMergeExtension.merge` / `.mergeFrom` are kept — `SortedListX`
  is on `List` and routes there for the new perf paths; the old
  extension still serves `Iterable<T>` callers in v10.
- `ChannelClientState._checkExpiredAttachmentMessages` removed (#2653);
  v10's `StreamImageCDN.cacheKey` already keeps the image cache valid
  across signed-URL rotations.
- `ChannelClientState.updateChannelState` now identity-short-circuits
  when `updatedState.messages` is null or the same reference, so
  downstream `.distinct()` listeners can skip rebuilds.
- Reaction listeners now dispatch via `_findMessage` (parentId-aware)
  while keeping v10's `addMyReaction` / `deleteMyReaction` semantics.

`stream_chat_flutter_core`
- `BetterStreamBuilder` correctness fixes: mounted guard, error reporting
  via `FlutterError.reportError`, identity-equal emission gating (#2651).
- `MessageListCore` caches its `messagesStream` / `_initialMessages` as
  fields instead of recomputing in `build()` (#2651). `defaultMessageFilter`
  takes an optional `currentUserId`.
- `StreamChatCore` debounces connectivity events to 3 s (#2652).

`stream_chat_flutter`
- `scrollable_positioned_list/`: master version taken in full. Bounded
  `_keyToIndexMap`, `isScrolling` / `isScrollingListenable`,
  `itemKeyBuilder` anchor preservation, fit-anchor fallback in
  `UnboundedRenderViewport`, sensible defaults on `scrollTo` (#2651).
- `tld.dart` removed (#2654); `StreamMessageComposer` relaxed its URL
  regex from `[a-z]{2,4}` to `[a-z]{2,}` and dropped the `isValidTLD`
  filter at both call sites.
- `StreamMessageListView` and `separated_reorderable_list_view`:
  v10's design-refresh version retained. v10 already covers the
  functional surface; master's identity-preserving micro-optimizations
  to `updateMessage` are a follow-up.

CI / repo
- Path/draft gating job (`gate`) added to `legacy_version_analyze`,
  `check_db_entities`, and `stream_flutter_workflow` (#2669).
- Flutter 3.44 fixes (#2667), pana / build cleanups (#2656),
  local-setup CI fixes (#2650).
- `melos.yaml`: kept v10's higher floors; added `firebase_crashlytics`
  (master's #2665); dropped `sentry_flutter` (per master).

Notes / follow-ups
- `sample_app/`: v10's redesigned app retained. The Sentry → Firebase
  Crashlytics migration (#2665) applies to master's pre-redesign sample
  app and was not ported here; left for a separate pass.
- `channel_test.dart` `updateMessage quoted-rewrite > does not rewrite
  quotes when an existing quoted target is updated without being
  deleted` is marked `skip:` — v10's `_updateMessages` reconstructs the
  channel list via `_mergeMessagesIntoExisting`, so identity is not
  preserved on non-deletion edits. Functional behavior matches master.
- `goldens/`: deleted-on-v10 goldens kept deleted; modified-on-both
  goldens kept at v10's bytes (the redesigned UI is the source of
  truth).
- `stream_message_composer.dart` had `SizeTransition(alignment:)` which
  was never a valid parameter — switched to `axisAlignment: -1` (the
  Flutter API the v10 author intended).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xsahil03x added a commit that referenced this pull request May 20, 2026
Brings master's QA / security / perf work into the v10 design-refresh
branch.

Highlights of what landed in v10 from master:

LLC (`stream_chat`)
- `Client.queryDrafts` now forwards `filter` (#2647).
- `Client.queryChannels` coalesces concurrent identical queries via the
  new `InFlightCache<K, V>` (#2652).
- `SortedListX` / `ListX` extensions added in `list_extensions.dart`;
  duplicate-keyed inputs are tolerated by `merge` (#2660). v10's
  `IterableMergeExtension.merge` / `.mergeFrom` are kept — `SortedListX`
  is on `List` and routes there for the new perf paths; the old
  extension still serves `Iterable<T>` callers in v10.
- `ChannelClientState._checkExpiredAttachmentMessages` removed (#2653);
  v10's `StreamImageCDN.cacheKey` already keeps the image cache valid
  across signed-URL rotations.
- `ChannelClientState.updateChannelState` now identity-short-circuits
  when `updatedState.messages` is null or the same reference, so
  downstream `.distinct()` listeners can skip rebuilds.
- Reaction listeners now dispatch via `_findMessage` (parentId-aware)
  while keeping v10's `addMyReaction` / `deleteMyReaction` semantics.

`stream_chat_flutter_core`
- `BetterStreamBuilder` correctness fixes: mounted guard, error reporting
  via `FlutterError.reportError`, identity-equal emission gating (#2651).
- `MessageListCore` caches its `messagesStream` / `_initialMessages` as
  fields instead of recomputing in `build()` (#2651). `defaultMessageFilter`
  takes an optional `currentUserId`.
- `StreamChatCore` debounces connectivity events to 3 s (#2652).

`stream_chat_flutter`
- `scrollable_positioned_list/`: master version taken in full. Bounded
  `_keyToIndexMap`, `isScrolling` / `isScrollingListenable`,
  `itemKeyBuilder` anchor preservation, fit-anchor fallback in
  `UnboundedRenderViewport`, sensible defaults on `scrollTo` (#2651).
- `tld.dart` removed (#2654); `StreamMessageComposer` relaxed its URL
  regex from `[a-z]{2,4}` to `[a-z]{2,}` and dropped the `isValidTLD`
  filter at both call sites.
- `StreamMessageListView` and `separated_reorderable_list_view`:
  v10's design-refresh version retained. v10 already covers the
  functional surface; master's identity-preserving micro-optimizations
  to `updateMessage` are a follow-up.

CI / repo
- Path/draft gating job (`gate`) added to `legacy_version_analyze`,
  `check_db_entities`, and `stream_flutter_workflow` (#2669).
- Flutter 3.44 fixes (#2667), pana / build cleanups (#2656),
  local-setup CI fixes (#2650).
- `melos.yaml`: kept v10's higher floors; added `firebase_crashlytics`
  (master's #2665); dropped `sentry_flutter` (per master).

Notes / follow-ups
- `sample_app/`: v10's redesigned app retained. The Sentry → Firebase
  Crashlytics migration (#2665) applies to master's pre-redesign sample
  app and was not ported here; left for a separate pass.
- `channel_test.dart` `updateMessage quoted-rewrite > does not rewrite
  quotes when an existing quoted target is updated without being
  deleted` is marked `skip:` — v10's `_updateMessages` reconstructs the
  channel list via `_mergeMessagesIntoExisting`, so identity is not
  preserved on non-deletion edits. Functional behavior matches master.
- `goldens/`: deleted-on-v10 goldens kept deleted; modified-on-both
  goldens kept at v10's bytes (the redesigned UI is the source of
  truth).
- `stream_message_composer.dart` had `SizeTransition(alignment:)` which
  was never a valid parameter — switched to `axisAlignment: -1` (the
  Flutter API the v10 author intended).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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