Skip to content

Conversation

@xsahil03x
Copy link
Member

@xsahil03x xsahil03x commented Jun 16, 2025

Summary by CodeRabbit

  • New Features

    • Live & static location sharing with expiry, location APIs, labels and event support.
    • CDN upload/remove for images/files from the client.
    • Scoped delete controls including per-user "delete for me".
    • Reaction API now uses a Reaction object (emoji codes, timestamps).
    • Poll attachment UI, attachment picker customization, and platform widget improvements.
  • Bug Fixes

    • Fixed UTC conversion for location timestamps.
  • Documentation

    • Added detailed v10 migration guide and updated changelogs.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 16, 2025

Walkthrough

Adds live location sharing and persistence, scoped message deletion (delete-for-me), Reaction API refactor to use Reaction objects, an EventController with resolvers, CDN upload/remove endpoints, many model/serialization updates, UI refactors (polls, voice-recording removals), tests, and migration docs.

Changes

Cohort / File(s) Summary
Version & Manifests
\melos.yaml`, `packages/stream_chat/pubspec.yaml`, `packages/stream_chat/lib/version.dart`, `packages/stream_chat/example/pubspec.yaml`, `packages/stream_chat_flutter/example/pubspec.yaml``
Bumped package and package VERSION to 10.0.0-beta.10; added dependencies (avatar_glow, flutter_map, flutter_map_animations, geolocator, latlong2) and reordered dependencies.
Migration & Changelog
\migrations/v10-migration.md`, `packages/stream_chat/CHANGELOG.md`, `packages/stream_chat_flutter/CHANGELOG.md``
New migration guide and updated changelogs documenting v10 beta breaking changes and migration steps.
Event System
\packages/stream_chat/lib/src/core/util/event_controller.dart`, `packages/stream_chat/lib/src/client/event_resolvers.dart`, `packages/stream_chat/lib/src/event_type.dart`**`
Added EventController with resolver pipeline and several event resolvers; introduced new event types (poll., location., userMessagesDeleted).
Client & Channel
\packages/stream_chat/lib/src/client/client.dart`, `packages/stream_chat/lib/src/client/channel.dart`, `packages/stream_chat/lib/src/client/retry_queue.dart`**`
Added CDN upload/remove APIs, live location APIs/state and cleanup, deleteMessageForMe and scoped delete flows, unified retry handling for multiple failed states, null-safety fixes, and merge helpers.
CDN / Attachment Upload API
\packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart`**`
Added standalone uploadImage/uploadFile and removeImage/removeFile endpoints and implementations.
Message API / Responses
\packages/stream_chat/lib/src/core/api/message_api.dart`, `packages/stream_chat/lib/src/core/api/responses.dart`, `packages/stream_chat/lib/src/core/api/responses.g.dart`, `packages/stream_chat/lib/src/core/api/user_api.dart``
MessageApi.deleteMessage accepts deleteForMe; sendReaction accepts a Reaction object and skipPush; added GetActiveLiveLocationsResponse and user live-location endpoints.
Models — Locations & Deletion Scope
\packages/stream_chat/lib/src/core/models/location.dart`, `.../location.g.dart`, `.../location_coordinates.dart`, `packages/stream_chat/lib/src/core/models/message_delete_scope*.dart`, `packages/stream_chat/lib/src/core/models/channel_config.dart`, `packages/stream_chat/lib/src/core/models/channel_state.dart`, `packages/stream_chat/lib/src/core/models/event.dart``
Added Location and LocationCoordinates models; ChannelConfig/ChannelState extended for activeLiveLocations; introduced MessageDeleteScope union and Event.deletedForMe with JSON wiring.
Models — Message & MessageState
\packages/stream_chat/lib/src/core/models/message.dart`, `.../message.g.dart`, `packages/stream_chat/lib/src/core/models/message_state.*`**`
Message gained sharedLocation and deletedForMe; MessageState refactored to use MessageDeleteScope and new failure variants (sendingFailed, updatingFailed, partialUpdatingFailed) with skip flags.
Models — Reaction & ReactionGroup
\packages/stream_chat/lib/src/core/models/reaction.dart`, `.../reaction.g.dart`, `packages/stream_chat/lib/src/core/models/reaction_group.dart`**`
Reaction made Equatable, added emojiCode/createdAt/updatedAt adjustments and changed score default; added ReactionSorting comparators.
API Cleanup / Removals
\packages/stream_chat/lib/src/core/api/call_api.dart`, `packages/stream_chat/lib/src/core/models/call_payload.*`, `packages/stream_chat/lib/src/core/api/stream_chat_api.dart`, `packages/stream_chat/lib/src/core/models/permission_type.dart`, `packages/stream_chat/lib/stream_chat.dart``
Removed CallApi and CallPayload models, removed PermissionType and its export; updated public exports.
Persistence / DB
\packages/stream_chat/lib/src/db/chat_persistence_client.dart`, `packages/stream_chat/test/src/db/``
Added persistence methods for locations, deleteMessagesFromUser, optional messageLimit parameter in getChannelStates, and integrated locations into bulk updates.
Utilities
\packages/stream_chat/lib/src/core/util/extension.dart`, `packages/stream_chat/lib/src/core/util/message_rules.dart`**`
Added mergeFrom generic merge helper; MessageRules.canUpload now treats sharedLocation as uploadable.
Flutter UI — Attachments & Polls
\packages/stream_chat_flutter/lib/src/attachment/poll_attachment.dart`, `.../builder/poll_attachment_builder.dart`, `packages/stream_chat_flutter/lib/src/attachment/attachment.dart`**`
Introduced PollAttachment widget and PollAttachmentBuilder; exported new attachment types.
Flutter UI — Voice Recording Removals
\packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/*`**`
Removed deprecated voice-recording widgets/builders (player, list player, slider, loading) and related builder.
Flutter UI — Misc & Icons
\packages/stream_chat_flutter/lib/src/icons/stream_svg_icon.dart`, `packages/stream_chat_flutter/lib/platform_widget_builder/src/platform_widget_builder.dart`, `packages/stream_chat_flutter/lib/src/indicators/unread_indicator.dart`, `packages/stream_chat_flutter/lib/src/localization/translations.dart`, `packages/stream_chat_flutter/lib/src/message_action/message_action.dart`**`
Simplified StreamSvgIcon public API (removed deprecated factories/fields), added desktopOrWeb builder, changed default unread indicator constructor, added translations.locationLabel and StreamMessageAction container.
Attachment Handlers
\packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_*.dart`**`
Replaced deprecated allowCompression bool with compressionQuality int across handlers and removed deprecated parameters.
Context Menus & Related Removals
\packages/stream_chat_flutter/lib/src/context_menu_items/*`, `packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart`**`
Removed ContextMenuReactionPicker, DownloadMenuItem, StreamChatContextMenuItem; added private replacements (e.g., _DownloadMenuItem) where needed.
Tests & Fixtures
\packages/stream_chat/test/src/`, `packages/stream_chat/test/fixtures/*``
Expanded/updated tests for event resolvers, live locations, reaction API, delete-for-me scopes, file uploader, persistence; updated fixtures (active_live_locations, deleted_messages, reaction_groups, emoji_code).
Generated Code Changes
many \.g.dart`, `.freezed.dart`**`
Updated generated serialization and Freezed outputs for new fields, unions, partialUpdatingFailed, skip flags, and removed/added payloads.

Sequence Diagram(s)

sequenceDiagram
    participant UI
    participant Channel
    participant API
    participant EventController
    participant Client
    participant Persistence

    Note over UI,Channel: Start live location sharing
    UI->>Channel: startLiveLocationSharing(coords, endAt)
    Channel->>API: POST /messages (shared_location payload)
    API-->>EventController: WS message_new event
    EventController->>EventController: locationSharedResolver -> transforms to location.shared
    EventController-->>Client: emit location.shared
    Client->>Channel: merge location into activeLiveLocations
    Client->>Persistence: updateLocations([...])
Loading
sequenceDiagram
    participant UI
    participant Channel
    participant API
    participant Client
    participant Persistence

    Note over UI,API: Delete message for me
    UI->>Channel: deleteMessage(messageId, scope: deleteForMe)
    Channel->>API: DELETE /messages/{id}?delete_for_me=true
    API-->>Client: user.messages.deleted event
    Client->>Persistence: deleteMessagesFromUser(userId, cid?, deleteForMe)
    Client->>Channel: mark message.deletedForMe and update state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas to pay extra attention:

  • packages/stream_chat/lib/src/client/client.dart and channel.dart — live-location lifecycle, merge helpers, retry queue integration, delete-for-me flows.
  • message_state / message_delete_scope Freezed changes and JSON (de)serialization across generated files.
  • Message and Reaction model updates plus MessageApi.sendReaction/deleteMessage signature and payload changes.
  • EventController and event_resolvers ordering/short-circuit behavior and their tests.
  • Persistence/db changes for location storage and deleteMessagesFromUser integration.

Possibly related PRs

Suggested reviewers

  • renefloor

Poem

"I nibble code where markers glow,
I plant a scope where deletions grow,
I hop with maps and live-location show,
Emoji sparks and resolvers flow,
A rabbit cheers — v10, off we go!"

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(repo)!: v10.0.0' accurately describes the primary change: a major version bump to v10.0.0, reflected throughout the changeset including version updates, breaking API changes, and new features.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v10.0.0

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 302ade6 and e223a99.

⛔ Files ignored due to path filters (68)
  • 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_issue_2369.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/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/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/countdown_button_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_with_reactions_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_with_reactions_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_with_reactions_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_with_reactions_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_reversed_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_reversed_light.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/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_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
📒 Files selected for processing (7)
  • melos.yaml (4 hunks)
  • packages/stream_chat/CHANGELOG.md (7 hunks)
  • packages/stream_chat/example/pubspec.yaml (1 hunks)
  • packages/stream_chat/lib/version.dart (1 hunks)
  • packages/stream_chat/pubspec.yaml (1 hunks)
  • packages/stream_chat_flutter/CHANGELOG.md (7 hunks)
  • packages/stream_chat_flutter/example/pubspec.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/stream_chat_flutter/example/pubspec.yaml
  • packages/stream_chat/lib/version.dart
  • packages/stream_chat/CHANGELOG.md
  • packages/stream_chat/pubspec.yaml
  • packages/stream_chat/example/pubspec.yaml
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message with MessageSendingStatus.failed or MessageSendingStatus.failed_update status, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message with MessageSendingStatus.failed or MessageSendingStatus.failed_update status, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • melos.yaml
  • packages/stream_chat_flutter/CHANGELOG.md
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat_flutter/CHANGELOG.md
📚 Learning: 2025-08-08T14:27:59.621Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2348
File: packages/stream_chat_flutter_core/lib/src/stream_channel.dart:383-406
Timestamp: 2025-08-08T14:27:59.621Z
Learning: In stream_chat_flutter_core/lib/src/stream_channel.dart, threads (replies) do not support around-anchor loading. Thread replies are fetched as: initial latest page via StreamChannelState.getReplies(), and further pagination via StreamChannelState.queryReplies(parentId, direction: top|bottom). Anchored loads apply only to channel messages, not to threads.

Applied to files:

  • packages/stream_chat_flutter/CHANGELOG.md
🔇 Additional comments (5)
packages/stream_chat_flutter/CHANGELOG.md (3)

1-82: Verify memory heap fix is documented in v10.0.0 release notes.

The PR objectives reference a memory heap issue fix recommendation to add .truncate() to channel.dart's dispose() method for clearing accumulated channel messages. This appears to be missing from the v10.0.0-beta.10 entry (lines 1-4). If this is a critical fix being shipped with v10.0.0, it should be documented in the appropriate beta version entry or added to the final release notes.

Can you confirm:

  1. Is the memory heap fix included in this v10.0.0 release?
  2. If yes, which beta version introduced it, and should it be documented in this CHANGELOG?
  3. Should it be highlighted as a "Fixed" item given its performance impact?

12-82: Clear and comprehensive documentation of v10 breaking changes.

The v10.0.0-beta.9 and beta.8 entries provide excellent documentation of API changes with before/after code examples. This will significantly help developers with the migration process. The consistent reference to the migration guide (../../migrations/v10-migration.md) is also a strong practice.


80-80: Migration guide references are well-placed.

Links to the v10 migration guide are consistently positioned at the end of major breaking change sections, making them easy for users to find. This supports the "Chill" review approach by maintaining good navigation for developers.

Also applies to: 160-160, 268-268, 307-307

melos.yaml (2)

87-91: Verify stream_chat beta version is intentional for workspace dependencies.*

The stream_chat family of packages are pinned to ^10.0.0-beta.10, which is a pre-release version for a major release. While this aligns with the v10.0.0 feature branch objective, using beta versions in a monorepo's bootstrap dependencies carries risk if any consuming app or package expects a stable release.

Confirm that all consuming packages and apps explicitly declare compatibility with the beta versions, and verify that pre-release versions are acceptable for your release strategy. If this is a temporary measure for feature development, plan the cutover to stable releases before final merge to master.


28-28: New location feature dependencies are coherent and stable.

The addition of avatar_glow, flutter_map ^8.1.1, flutter_map_animations ^0.9.0, geolocator, and latlong2 ^0.9.1 is well-coordinated for the live location sharing feature. The dependency chain is sound (flutter_map and flutter_map_animations both consume latlong2, and versions are compatible). All except geolocator have recent stability records.

Ensure your integration tests validate the location data flow across all new packages, especially map rendering with animations and live location updates.

Also applies to: 47-48, 56-56, 66-66


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.

xsahil03x and others added 11 commits June 17, 2025 16:01
# Conflicts:
#	packages/stream_chat_flutter/CHANGELOG.md
# Conflicts:
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter_core/CHANGELOG.md
# Conflicts:
#	melos.yaml
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat/example/pubspec.yaml
#	packages/stream_chat/lib/version.dart
#	packages/stream_chat/pubspec.yaml
#	packages/stream_chat_flutter/example/pubspec.yaml
#	packages/stream_chat_flutter/pubspec.yaml
#	packages/stream_chat_flutter_core/example/pubspec.yaml
#	packages/stream_chat_flutter_core/pubspec.yaml
#	packages/stream_chat_localizations/CHANGELOG.md
#	packages/stream_chat_localizations/example/pubspec.yaml
#	packages/stream_chat_localizations/pubspec.yaml
#	packages/stream_chat_persistence/CHANGELOG.md
#	packages/stream_chat_persistence/example/pubspec.yaml
#	packages/stream_chat_persistence/pubspec.yaml
#	sample_app/pubspec.yaml
xsahil03x and others added 13 commits June 30, 2025 12:44
# Conflicts:
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat_flutter_core/CHANGELOG.md
# Conflicts:
#	melos.yaml
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat/example/pubspec.yaml
#	packages/stream_chat/lib/version.dart
#	packages/stream_chat/pubspec.yaml
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/example/pubspec.yaml
#	packages/stream_chat_flutter/pubspec.yaml
#	packages/stream_chat_flutter_core/example/pubspec.yaml
#	packages/stream_chat_flutter_core/pubspec.yaml
#	packages/stream_chat_localizations/CHANGELOG.md
#	packages/stream_chat_localizations/example/pubspec.yaml
#	packages/stream_chat_localizations/pubspec.yaml
#	packages/stream_chat_persistence/CHANGELOG.md
#	packages/stream_chat_persistence/example/pubspec.yaml
#	packages/stream_chat_persistence/pubspec.yaml
#	sample_app/pubspec.yaml
# Conflicts:
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat_flutter_core/CHANGELOG.md
# Conflicts:
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart
#	packages/stream_chat_persistence/CHANGELOG.md
The animation curves and durations for the reaction picker and message modal have been updated for a smoother user experience.

- The `reaction_picker_icon_list.dart` animation curve is now `Curves.easeOutBack` and the duration is 335 milliseconds.
- The `message_modal.dart` transition duration is now 335 milliseconds, and the scale animation curve is `Curves.easeOutBack`.
xsahil03x and others added 19 commits September 24, 2025 14:14
# Conflicts:
#	melos.yaml
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat/example/pubspec.yaml
#	packages/stream_chat/lib/src/client/channel.dart
#	packages/stream_chat/lib/src/core/models/channel_config.dart
#	packages/stream_chat/lib/src/core/models/channel_config.g.dart
#	packages/stream_chat/lib/src/core/models/message.dart
#	packages/stream_chat/lib/src/core/models/message.g.dart
#	packages/stream_chat/lib/version.dart
#	packages/stream_chat/pubspec.yaml
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/example/pubspec.yaml
#	packages/stream_chat_flutter/pubspec.yaml
#	packages/stream_chat_flutter_core/CHANGELOG.md
#	packages/stream_chat_flutter_core/example/pubspec.yaml
#	packages/stream_chat_flutter_core/pubspec.yaml
#	packages/stream_chat_localizations/CHANGELOG.md
#	packages/stream_chat_localizations/example/pubspec.yaml
#	packages/stream_chat_localizations/pubspec.yaml
#	packages/stream_chat_persistence/CHANGELOG.md
#	packages/stream_chat_persistence/example/pubspec.yaml
#	packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart
#	packages/stream_chat_persistence/pubspec.yaml
#	sample_app/pubspec.yaml
# Conflicts:
#	melos.yaml
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat/example/pubspec.yaml
#	packages/stream_chat/lib/version.dart
#	packages/stream_chat/pubspec.yaml
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/example/pubspec.yaml
#	packages/stream_chat_flutter/pubspec.yaml
#	packages/stream_chat_flutter_core/CHANGELOG.md
#	packages/stream_chat_flutter_core/example/pubspec.yaml
#	packages/stream_chat_flutter_core/pubspec.yaml
#	packages/stream_chat_localizations/CHANGELOG.md
#	packages/stream_chat_localizations/example/pubspec.yaml
#	packages/stream_chat_localizations/pubspec.yaml
#	packages/stream_chat_persistence/CHANGELOG.md
#	packages/stream_chat_persistence/example/pubspec.yaml
#	packages/stream_chat_persistence/pubspec.yaml
#	sample_app/pubspec.yaml
# Conflicts:
#	melos.yaml
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat/example/pubspec.yaml
#	packages/stream_chat/lib/src/client/channel.dart
#	packages/stream_chat/lib/src/client/client.dart
#	packages/stream_chat/lib/src/core/models/channel_config.dart
#	packages/stream_chat/lib/src/core/models/channel_config.g.dart
#	packages/stream_chat/lib/src/event_type.dart
#	packages/stream_chat/lib/stream_chat.dart
#	packages/stream_chat/lib/version.dart
#	packages/stream_chat/pubspec.yaml
#	packages/stream_chat/test/src/client/channel_test.dart
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/example/pubspec.yaml
#	packages/stream_chat_flutter/lib/src/channel/stream_message_preview_text.dart
#	packages/stream_chat_flutter/lib/src/stream_chat_configuration.dart
#	packages/stream_chat_flutter/pubspec.yaml
#	packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_1.png
#	packages/stream_chat_flutter/test/src/indicators/goldens/ci/sending_indicator_2.png
#	packages/stream_chat_flutter/test/src/theme/message_theme_test.dart
#	packages/stream_chat_flutter_core/CHANGELOG.md
#	packages/stream_chat_flutter_core/example/pubspec.yaml
#	packages/stream_chat_flutter_core/pubspec.yaml
#	packages/stream_chat_localizations/CHANGELOG.md
#	packages/stream_chat_localizations/example/pubspec.yaml
#	packages/stream_chat_localizations/pubspec.yaml
#	packages/stream_chat_persistence/CHANGELOG.md
#	packages/stream_chat_persistence/example/pubspec.yaml
#	packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart
#	packages/stream_chat_persistence/pubspec.yaml
#	sample_app/lib/pages/channel_page.dart
#	sample_app/pubspec.yaml
@xsahil03x xsahil03x marked this pull request as ready for review November 18, 2025 16:01
@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

❌ Patch coverage is 63.65727% with 632 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.50%. Comparing base (c0fd5f8) to head (ee5d767).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...flutter/lib/src/message_widget/message_widget.dart 29.31% 164 Missing ⚠️
...ut/attachment_picker/stream_attachment_picker.dart 23.37% 118 Missing ⚠️
...nt_picker/stream_attachment_picker_controller.dart 7.86% 82 Missing ⚠️
packages/stream_chat/lib/src/client/channel.dart 83.46% 63 Missing ⚠️
...er/lib/src/message_input/stream_message_input.dart 7.69% 24 Missing ⚠️
...ssage_modal/message_action_confirmation_modal.dart 0.00% 22 Missing ⚠️
...ib/src/message_action/message_actions_builder.dart 80.58% 20 Missing ⚠️
...rc/fullscreen_media/full_screen_media_desktop.dart 0.00% 19 Missing ⚠️
...lib/src/message_widget/message_widget_content.dart 75.64% 19 Missing ⚠️
...r/lib/src/message_list_view/message_list_view.dart 15.78% 16 Missing ⚠️
... and 19 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2280      +/-   ##
==========================================
+ Coverage   64.62%   66.50%   +1.88%     
==========================================
  Files         420      428       +8     
  Lines       26210    26566     +356     
==========================================
+ Hits        16938    17668     +730     
+ Misses       9272     8898     -374     

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

Copy link
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.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/stream_chat/lib/src/core/api/sort_order.dart (1)

37-65: Update class-level documentation example to use new constructor API

Migration from the unnamed constructor and SortOption.fromJson is complete across the codebase. All test and library code consistently uses the new SortOption.desc() and SortOption.asc() constructors, and the generated .g.dart file correctly omits fromJson due to createFactory: false.

However, the class-level documentation (before line 37) still references the old unnamed constructor syntax SortOption<ChannelState>("last_message_at"). Update this example to use the new API: either SortOption.desc(...) or SortOption.asc(...) for consistency with the constructor-level docs and to avoid misleading developers.

packages/stream_chat_flutter/lib/src/icons/stream_svg_icon.dart (1)

100-110: Add null check before passing icon to SvgIcon widget.

The SvgIcon widget from the svg_icon_widget package does not accept null parameters. However, the code at line 103 passes icon (a nullable parameter) directly without checking, and the documentation claims the widget should render empty space when icon is null. This will cause a runtime crash if icon is null.

Fix: Wrap the SvgIcon call in a null check:

@override
Widget build(BuildContext context) {
  return icon != null
    ? SvgIcon(
        icon,
        size: size,
        color: color,
        textDirection: textDirection,
        applyTextScaling: applyTextScaling,
        semanticLabel: semanticLabel,
      )
    : SizedBox(width: size, height: size);
}
packages/stream_chat/lib/src/core/models/message_state.dart (1)

755-825: FailedStatePatternMatching.whenOrNull/maybeWhen make partialUpdatingFailed mandatory

In FailedStatePatternMatching:

  • whenOrNull and maybeWhen declare partialUpdatingFailed as a required parameter and call it directly (not via ?.call), while the other callbacks are optional and null-checked.

This means callers cannot use whenOrNull/maybeWhen to intentionally ignore the partialUpdatingFailed case the way they can for the other variants, which is inconsistent with the rest of the pattern-matching API and may cause surprising compile-time breakage for existing uses that only care about a subset of failure kinds.

Consider making partialUpdatingFailed optional here as well:

TResult? whenOrNull<TResult extends Object?>({
  TResult? Function(bool skipPush, bool skipEnrichUrl)? sendingFailed,
  TResult? Function(bool skipPush, bool skipEnrichUrl)? updatingFailed,
  TResult? Function(
    Map<String, Object?>? set,
    List<String>? unset,
    bool skipEnrichUrl,
  )? partialUpdatingFailed,
  TResult? Function(MessageDeleteScope scope)? deletingFailed,
}) {
  final failedState = this;
  return switch (failedState) {
    SendingFailed() =>
      sendingFailed?.call(failedState.skipPush, failedState.skipEnrichUrl),
    UpdatingFailed() =>
      updatingFailed?.call(failedState.skipPush, failedState.skipEnrichUrl),
    PartialUpdatingFailed() => partialUpdatingFailed?.call(
      failedState.set,
      failedState.unset,
      failedState.skipEnrichUrl,
    ),
    DeletingFailed() => deletingFailed?.call(failedState.scope),
  };
}

and similarly for maybeWhen.

🧹 Nitpick comments (25)
packages/stream_chat_flutter/lib/src/message_action/message_action.dart (1)

48-55: Align title docs with its Widget? type.

Docs talk specifically about using Text and Text.maxLines, but title is a generic Widget?; consider either tightening the type to Text? or slightly rephrasing the doc to note that Text is the typical usage while still allowing arbitrary widgets.

packages/stream_chat_flutter/lib/platform_widget_builder/src/platform_widget_builder.dart (1)

43-47: Well-documented fallback field.

The field declaration and documentation clearly explain the fallback behavior. Consider adding a usage example to illustrate when desktopOrWeb is beneficial:

/// Example:
/// ```dart
/// PlatformWidgetBuilder(
///   mobile: (context, child) => MobileView(child: child),
///   desktopOrWeb: (context, child) => DesktopWebView(child: child),
/// )
/// ```
packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart (1)

392-436: Download menu item implementation is sound; consider decoupling from maybePop

The new _DownloadMenuItem correctly builds a StreamMessageActionItem using CustomMessageAction and StreamAttachmentHandler.instance.downloadAttachment, with safe type checks on action and attachment. Implementation looks solid.

One small improvement you might consider later: calling downloadAttachment even when maybePop returns false, so the download isn’t tightly coupled to the ability to pop the current route (e.g., if the menu is not on its own navigator). This can be done by awaiting maybePop only to close the menu, but always triggering the download afterward.

packages/stream_chat/lib/src/core/api/sort_order.dart (1)

32-36: Update docs/examples to match new constructors and null ordering defaults

There are a few documentation inconsistencies after introducing SortOption.desc / SortOption.asc:

  • Lines 32–36 and 98–100 still show the old unnamed constructor, which no longer exists.
  • Lines 81–82 say the default is always NullOrdering.nullsFirst, but SortOption.asc now defaults to NullOrdering.nullsLast while SortOption.desc keeps NullOrdering.nullsFirst.

Consider updating the comments, for example:

 /// Example:
 /// ```dart
-/// // Sort channels by last message date in descending order
-/// final sort = SortOption<ChannelState>("last_message_at");
+/// // Sort channels by last message date in descending order
+/// final sort = SortOption.desc<ChannelState>("last_message_at");
 /// ```
@@
-  /// Defaults to `NullOrdering.nullsFirst`, which treats null values as less
-  /// than any non-null value.
+  /// Default depends on the constructor:
+  /// - `SortOption.desc`: `NullOrdering.nullsFirst`
+  /// - `SortOption.asc`: `NullOrdering.nullsLast`
+  /// In both cases, nulls are treated consistently regardless of sort direction.
@@
-  /// ```dart
-  /// final sortOption = SortOption<ChannelState>("last_message_at");
-  /// final sortedChannels = channels.sort(sortOption.compare);
-  /// ```
+  /// ```dart
+  /// final sortOption = SortOption.desc<ChannelState>("last_message_at");
+  /// final sortedChannels = channels..sort(sortOption.compare);
+  /// ```

This will prevent confusion for users upgrading to v10 who rely on the inline examples and docs.

Also applies to: 79-85, 98-100

packages/stream_chat/lib/src/core/models/location_coordinates.dart (1)

3-7: Fix documentation template tag mismatch.

The template tag uses locationInfo but should match the class name LocationCoordinates for consistency with Dart documentation conventions.

Apply this diff:

-/// {@template locationInfo}
+/// {@template locationCoordinates}
 /// A model class representing a location with latitude and longitude.
 /// {@endtemplate}
 class LocationCoordinates extends Equatable {
-  /// {@macro locationInfo}
+  /// {@macro locationCoordinates}
   const LocationCoordinates({
packages/stream_chat/CHANGELOG.md (1)

1-7: Consider versioning the "Upcoming Beta" section.

The "Upcoming Beta" header suggests an unreleased fix for Location.endAt UTC conversion. Consider assigning this a proper version number (e.g., 10.0.0-beta.9) to maintain clear version history.

packages/stream_chat/lib/src/db/chat_persistence_client.dart (1)

90-95: Consider explicit lifecycle handling for persisted Location rows.

The new location APIs and the updateChannelStates integration (collecting message.sharedLocation / pinnedMessage.sharedLocation into a locations list and calling updateLocations(locations)) make sense, but the deletion story is less explicit:

  • There’s no call to deleteLocationsByCid / deleteLocationsByMessageIds in updateChannelStates, unlike the explicit cleanup used for drafts and poll votes.
  • If a message’s sharedLocation can transition from non-null to null (e.g., location share ended and the field is cleared), you may end up with stale Location rows unless updateLocations or FK cascades handle this internally.

If the intended behavior is “locations are immutable and only expire via flags, not by removing sharedLocation,” this is fine; otherwise, it may be worth either:

  • Documenting that updateLocations is expected to fully reconcile state (e.g., by deleting missing entries for the affected cids/messageIds), or
  • Adding calls to deleteLocationsByCid/deleteLocationsByMessageIds analogous to drafts/pollVotes before updateLocations.

Also applies to: 176-192, 201-206, 267-268, 345-347, 397-401, 441-447

packages/stream_chat/test/src/core/util/event_controller_test.dart (2)

9-20: Avoid leaking the EventController created in setUp when reassigning

You create a fresh EventController in setUp, but several tests later reassign controller = EventController<Event>(...) without closing the original instance first. tearDown only closes the last assigned controller, so the initial one from setUp is effectively leaked in those tests.

In practice this is unlikely to break anything, but for cleanliness you could either:

  • Instantiate the controller only in tests that need custom configuration (and skip the setUp default there), or
  • Explicitly await controller.close() before reassigning in those tests.

35-64: Clarify resolver semantics in test description

Given EventController short‑circuits on the first resolver that returns a non‑null event (as verified by the next test), this test:

test('should apply resolvers in order', () async { ... });

asserts that only the first resolver’s transformation (message.newpoll.created) is applied, even though a second resolver exists.

To better reflect the behavior under test, consider renaming the description to something like “applies the first matching resolver” or adjusting the scenario if you want to truly test ordered fall‑through behavior.

packages/stream_chat/test/src/core/models/message_test.dart (1)

290-307: Good constructor coverage for reactionGroups (minor duplication only)

The new test verifying that Message uses the reactionGroups provided directly in the constructor is helpful and checks both count and sumScores for multiple keys.

If you want to DRY it up slightly, you could reuse the reactionGroupLike / reactionGroupLove instances defined above instead of constructing new ReactionGroups inline, but that’s purely cosmetic.

migrations/v10-migration.md (1)

1-916: Migration guide content is clear; only minor markdown‑lint nits

The guide is thorough and aligns with the code changes (Reaction object, delete‑for‑me, attachment picker refactors, etc.). The only issues I see are markdown‑lint/style nits (e.g., bold “Example:” / “Important:” lines being treated as headings, and a couple of minor grammar suggestions from LanguageTool). If you care about a clean markdownlint run, you could:

  • Turn repeated **Example: ...** blocks into lower‑level headings (e.g., #### Example: ...) or disable MD036 for this file.
  • Optionally tweak a few phrases where the linter suggested hyphenation or alternative wording.

None of this blocks merging; it’s purely cosmetic.

packages/stream_chat/lib/src/core/models/location.dart (1)

71-85: Doc comments still reference “reminder” instead of location

The docs for createdByDeviceId, createdAt, and updatedAt talk about “the reminder” rather than “the shared location”, which looks like copy‑paste from another model. Updating those to refer to “location” will avoid confusion in the public API docs.

packages/stream_chat/lib/src/core/api/message_api.dart (1)

216-233: Update sendReaction docs to match the new Reaction‑based signature

The implementation now correctly accepts a Reaction object and forwards reaction.toJson() along with skip_push/enforce_unique, matching the v10 migration guide. The method docs still reference a [reactionType] parameter, though, which is misleading.

Recommend updating the comment block to describe:

  • The reaction parameter (full Reaction object, including optional emojiCode, score, extraData, etc.).
  • That skipPush and enforceUnique remain as separate flags.

Behavior is fine; this is just an API documentation cleanup.

packages/stream_chat/lib/src/core/models/member.dart (1)

29-31: Member.deletedMessages wiring looks consistent with the new delete-for-me semantics

  • Field is correctly defaulted, added to _topLevelFields, threaded through copyWith, and included in props, so (de)serialization and equality should behave as expected.
  • Minor optional nit: the docstring “for himself” (Line 103) could be made gender-neutral (“for themselves”) for consistency with typical docs style, but it’s not functionally significant.

Also applies to: 57-59, 103-107, 129-149, 172-173

packages/stream_chat/lib/src/core/models/message.dart (2)

83-104: Deleted-for-me and shared-location modelling and state derivation look coherent

  • deletedForMe is correctly plumbed through constructor, field, topLevelFields, copyWith, merge, and props, and fromJson prioritizes deletedForMe over deletedAt when deriving both type and state. That matches the intended semantics of a per-user delete overriding global soft-delete handling.
  • sharedLocation’s addition (including import, field, @JsonKey(includeIfNull: false), topLevelFields, copyWith, merge, and props) lines up with the new location-sharing feature and the event resolvers that depend on message.sharedLocation.
  • Note that copyWith(sharedLocation: null) and copyWith(deletedForMe: null) will keep the existing values (standard pattern in this class). If you ever need to actively clear these fields with copyWith, you’d need a sentinel approach similar to quotedMessage/draft—but this can stay as-is if all clearing flows come from fresh server payloads.

Also applies to: 55-56, 331-341, 391-393, 452-454, 532-534, 580-582, 648-650


134-168: Reaction group backfill from legacy counts/scores is reasonable; consider stricter guards

  • _reactionGroupsReadValue correctly prefers an existing reaction_groups map, and otherwise reconstructs groups from reaction_counts/reaction_scores, which should smooth migration without breaking consumers of reactionGroups.
  • You currently skip any type where either count or sumScores is 0. If the backend ever sends reaction_counts without reaction_scores, that would drop valid reactions. If that’s a realistic scenario, consider treating a missing reaction_scores[type] as count (or at least not skipping when count > 0 and sumScores == 0).
  • Using DateTime.timestamp() for both first_reaction_at and last_reaction_at is fine as a placeholder; if these timestamps ever become user-visible, you might want a comment clarifying that they’re synthesized.

Also applies to: 167-168, 845-945

packages/stream_chat/test/src/db/chat_persistence_client_test.dart (1)

9-10: Persistence test stub updates are consistent; consider avoiding UnimplementedError for new API

  • The new overrides (deleteMessagesFromUser, location getters/updaters/deleters, and messageLimit on getChannelStates) correctly satisfy the updated ChatPersistenceClient interface and keep existing tests compiling.
  • Optional: for deleteMessagesFromUser, you currently throw UnimplementedError(), whereas most other “no-op” persistence operations here return Future.value(). If this stub ever gets reused beyond this test, aligning it to a no-op implementation would avoid surprising runtime errors.

Also applies to: 52-58, 90-95, 193-207

packages/stream_chat/lib/src/core/models/message_delete_scope.dart (1)

1-61: MessageDeleteScope union is cleanly designed and matches the new deletion semantics

  • The deleteForMe / deleteForAll(hard) variants, predefined softDeleteForAll/hardDeleteForAll, and fromJson factory give a clear, extensible representation for delete scope.
  • MessageDeleteScopeX.hard correctly returns false for DeleteForMe and delegates to the hard flag for DeleteForAll, which will simplify call sites.
  • Tiny doc nit only if you touch the file again: “Creates a instance” (Line 30) → “Creates an instance”.
packages/stream_chat/test/src/core/api/message_api_test.dart (1)

204-220: Tests correctly exercise delete-for-me and Reaction-based APIs

  • deleteMessage test now asserts queryParameters: {'delete_for_me': true} and calls deleteMessage(messageId, deleteForMe: true), which matches the new scoped deletion semantics.
  • sendReaction tests now build and pass a Reaction instance and expect the request body to be jsonEncode({'reaction': reaction.toJson(), 'skip_push': false, 'enforce_unique': …}), and validate that the response embeds message_id inside the reaction. This aligns with the new Reaction-centric API surface.
  • getReactions test expects each returned reaction JSON to include message_id, and verifies all parsed reactions have messageId == messageId, which should catch any regressions in the deserialization shape.

The stubbing via jsonEncode means the implementation must also encode the payload to a JSON string; that’s fine, just be aware that switching back to a raw map in MessageApi would require updating these expectations.

Also applies to: 255-321, 340-365

packages/stream_chat/lib/src/client/client.dart (2)

948-1008: Minor doc/parameter name mismatch in upload helpers

The docs for uploadImage/uploadFile reference [onProgress], but the actual parameter is named onUploadProgress and is forwarded to onSendProgress. It’s purely a documentation mismatch, but updating the references to [onUploadProgress] would avoid confusion for callers.

-  /// Upload progress can be tracked using [onProgress], and the operation can
+  /// Upload progress can be tracked using [onUploadProgress], and the operation can
@@
-  /// Upload progress can be tracked using [onProgress], and the operation can
+  /// Upload progress can be tracked using [onUploadProgress], and the operation can

1767-1780: Consider asserting consistency between messageId and reaction.messageId

sendReaction now takes both a messageId arg and a Reaction instance; only the messageId is used for the request path, so calls remain correct even if reaction.messageId is null or mismatched. To catch accidental inconsistencies early, you could add a debug assertion that, when set, reaction.messageId matches messageId.

   Future<SendReactionResponse> sendReaction(
     String messageId,
     Reaction reaction, {
     bool skipPush = false,
     bool enforceUnique = false,
   }) =>
-      _chatApi.message.sendReaction(
-        messageId,
-        reaction,
-        skipPush: skipPush,
-        enforceUnique: enforceUnique,
-      );
+      _chatApi.message.sendReaction(
+        (() {
+          assert(
+            reaction.messageId == null || reaction.messageId == messageId,
+            'reaction.messageId must match messageId',
+          );
+          return messageId;
+        })(),
+        reaction,
+        skipPush: skipPush,
+        enforceUnique: enforceUnique,
+      );

Also applies to: 3381-3409

packages/stream_chat/lib/src/client/channel.dart (4)

1186-1250: Location sending helpers: consider clarifying device/user requirements

The sendStaticLocation/startLiveLocationSharing helpers build a Message with an embedded Location using channelCid, currentUserId, and createdByDeviceId, then delegate to sendMessage. Structurally that’s fine, but it would help to document (or assert) expectations that:

  • client.state.currentUser is non-null when these are called, and
  • createdByDeviceId should be non-null when you expect multiple devices per user to share locations concurrently.

If those are intentionally optional, no change required; just worth double‑checking the backend expectations.


3213-3232: Message removal now consistently updates all views

updateMessage, cleanUpStaleErrorMessages, removeMessage, and deleteMessage delegating into _updateMessages / _removeMessages is a good consolidation. It guarantees that any addition/removal/change of a message is reflected across:

  • channel messages,
  • threads,
  • pinned messages,
  • active live locations,
    and persistence, rather than having ad-hoc per-caller logic.

3688-3750: Expired live location cleaner is sensible; verify client-side expiry policy

_startCleaningExpiredLocations periodically scans activeLiveLocations, skips locations from the current user (handled elsewhere), and synthesizes locationExpired events for other users’ expired shares. That’s a neat way to self-heal when explicit expiry events are missed.

One thing to confirm is that this “client-side expiry” behavior is aligned with server semantics (e.g., tolerance around clock skew and end time) so we don’t expire locations locally significantly earlier than the backend does.


3770-4147: Unified message merge/remove helpers cover main invariants; slight complexity tradeoff

The new helpers:

  • _deleteMessagesFromUser + _deleteMessages
  • _updateMessages and its four subpaths (threads, channel, pinned, active locations)
  • _mergeMessagesIntoExisting / _mergePinnedMessagesIntoExisting / _mergeActiveLocationsIntoExisting
  • _removeMessagesFromExisting and the corresponding remove helpers

give a single source of truth for how messages are added/updated/removed across channel messages, threads, pins, live locations, and persistence, while correctly updating quoted-message references and lastMessageAt. This significantly improves consistency and maintainability despite increasing the abstraction layer count.

Given the complexity here, it’s worth making sure there are dedicated tests around:

  • deleting messages that are only in threads vs shown in-channel,
  • deleting pinned messages and quoted messages,
  • deleting messages that own live locations (ensuring active locations are dropped),
  • userMessagesDeleted events for both hard and soft deletes.

If those tests already exist or are being added elsewhere in this PR, this structure looks good.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0292922 and b5874a1.

⛔ Files ignored due to path filters (102)
  • 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_issue_2369.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/icons/goldens/ci/stream_svg_icon_light.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/message_action/goldens/ci/stream_message_action_item_custom_child_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_custom_child_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_custom_styling_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_custom_styling_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_delete_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_delete_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_reply_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_action/goldens/ci/stream_message_action_item_reply_light.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/countdown_button_0.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/moderated_message_actions_modal_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/moderated_message_actions_modal_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_with_reactions_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_reversed_with_reactions_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_with_reactions_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_actions_modal_with_reactions_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_light.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_reversed_dark.png is excluded by !**/*.png
  • packages/stream_chat_flutter/test/src/message_modal/goldens/ci/stream_message_reactions_modal_reversed_light.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/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_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_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
📒 Files selected for processing (107)
  • melos.yaml (4 hunks)
  • migrations/v10-migration.md (1 hunks)
  • packages/stream_chat/CHANGELOG.md (7 hunks)
  • packages/stream_chat/example/pubspec.yaml (1 hunks)
  • packages/stream_chat/lib/src/client/channel.dart (27 hunks)
  • packages/stream_chat/lib/src/client/client.dart (15 hunks)
  • packages/stream_chat/lib/src/client/event_resolvers.dart (1 hunks)
  • packages/stream_chat/lib/src/client/retry_queue.dart (1 hunks)
  • packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart (2 hunks)
  • packages/stream_chat/lib/src/core/api/call_api.dart (0 hunks)
  • packages/stream_chat/lib/src/core/api/message_api.dart (3 hunks)
  • packages/stream_chat/lib/src/core/api/responses.dart (3 hunks)
  • packages/stream_chat/lib/src/core/api/responses.g.dart (1 hunks)
  • packages/stream_chat/lib/src/core/api/sort_order.dart (1 hunks)
  • packages/stream_chat/lib/src/core/api/sort_order.g.dart (0 hunks)
  • packages/stream_chat/lib/src/core/api/stream_chat_api.dart (0 hunks)
  • packages/stream_chat/lib/src/core/api/user_api.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/call_payload.dart (0 hunks)
  • packages/stream_chat/lib/src/core/models/call_payload.g.dart (0 hunks)
  • packages/stream_chat/lib/src/core/models/channel_config.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/channel_config.g.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/channel_model.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/channel_state.dart (5 hunks)
  • packages/stream_chat/lib/src/core/models/channel_state.g.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/event.dart (5 hunks)
  • packages/stream_chat/lib/src/core/models/event.g.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/location.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/location.g.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/location_coordinates.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/member.dart (6 hunks)
  • packages/stream_chat/lib/src/core/models/member.g.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/message.dart (14 hunks)
  • packages/stream_chat/lib/src/core/models/message.g.dart (4 hunks)
  • packages/stream_chat/lib/src/core/models/message_delete_scope.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/message_delete_scope.freezed.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/message_delete_scope.g.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/message_state.dart (27 hunks)
  • packages/stream_chat/lib/src/core/models/message_state.freezed.dart (15 hunks)
  • packages/stream_chat/lib/src/core/models/message_state.g.dart (2 hunks)
  • packages/stream_chat/lib/src/core/models/reaction.dart (4 hunks)
  • packages/stream_chat/lib/src/core/models/reaction.g.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/reaction_group.dart (1 hunks)
  • packages/stream_chat/lib/src/core/util/event_controller.dart (1 hunks)
  • packages/stream_chat/lib/src/core/util/extension.dart (2 hunks)
  • packages/stream_chat/lib/src/core/util/message_rules.dart (1 hunks)
  • packages/stream_chat/lib/src/db/chat_persistence_client.dart (8 hunks)
  • packages/stream_chat/lib/src/event_type.dart (3 hunks)
  • packages/stream_chat/lib/src/permission_type.dart (0 hunks)
  • packages/stream_chat/lib/stream_chat.dart (1 hunks)
  • packages/stream_chat/lib/version.dart (1 hunks)
  • packages/stream_chat/pubspec.yaml (1 hunks)
  • packages/stream_chat/test/fixtures/channel_state_to_json.json (25 hunks)
  • packages/stream_chat/test/fixtures/member.json (1 hunks)
  • packages/stream_chat/test/fixtures/message.json (1 hunks)
  • packages/stream_chat/test/fixtures/message_to_json.json (0 hunks)
  • packages/stream_chat/test/fixtures/reaction.json (1 hunks)
  • packages/stream_chat/test/src/client/client_test.dart (10 hunks)
  • packages/stream_chat/test/src/client/event_resolvers_test.dart (1 hunks)
  • packages/stream_chat/test/src/client/retry_queue_test.dart (2 hunks)
  • packages/stream_chat/test/src/core/api/attachment_file_uploader_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/api/call_api_test.dart (0 hunks)
  • packages/stream_chat/test/src/core/api/message_api_test.dart (4 hunks)
  • packages/stream_chat/test/src/core/api/responses_test.dart (0 hunks)
  • packages/stream_chat/test/src/core/api/sort_order_test.dart (0 hunks)
  • packages/stream_chat/test/src/core/api/user_api_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/models/call_payload_test.dart (0 hunks)
  • packages/stream_chat/test/src/core/models/channel_state_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/models/location_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/models/member_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/models/message_state_test.dart (7 hunks)
  • packages/stream_chat/test/src/core/models/message_test.dart (2 hunks)
  • packages/stream_chat/test/src/core/models/reaction_test.dart (7 hunks)
  • packages/stream_chat/test/src/core/util/event_controller_test.dart (1 hunks)
  • packages/stream_chat/test/src/core/util/message_rules_test.dart (1 hunks)
  • packages/stream_chat/test/src/db/chat_persistence_client_test.dart (4 hunks)
  • packages/stream_chat/test/src/mocks.dart (2 hunks)
  • packages/stream_chat_flutter/CHANGELOG.md (7 hunks)
  • packages/stream_chat_flutter/dart_test.yaml (1 hunks)
  • packages/stream_chat_flutter/example/pubspec.yaml (1 hunks)
  • packages/stream_chat_flutter/lib/platform_widget_builder/src/platform_widget_builder.dart (2 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/attachment.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/attachment_widget_catalog.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/attachment_widget_builder.dart (3 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/poll_attachment_builder.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/url_attachment_builder.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_list_player.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_loading.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_player.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_slider.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/voice_recording_attachment_builder.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_base.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/poll_attachment.dart (3 hunks)
  • packages/stream_chat_flutter/lib/src/attachment/voice_recording_attachment_playlist.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/attachment_actions_modal/attachment_actions_modal.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/autocomplete/stream_command_autocomplete_options.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/bottom_sheets/edit_message_sheet.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/context_menu_items/context_menu_reaction_picker.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/context_menu_items/download_menu_item.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/context_menu_items/stream_chat_context_menu_item.dart (0 hunks)
  • packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart (3 hunks)
  • packages/stream_chat_flutter/lib/src/icons/stream_svg_icon.dart (2 hunks)
  • packages/stream_chat_flutter/lib/src/indicators/unread_indicator.dart (1 hunks)
  • packages/stream_chat_flutter/lib/src/localization/translations.dart (5 hunks)
  • packages/stream_chat_flutter/lib/src/message_action/message_action.dart (1 hunks)
⛔ Files not processed due to max files limit (40)
  • packages/stream_chat_flutter/lib/src/message_action/message_action_item.dart
  • packages/stream_chat_flutter/lib/src/message_action/message_action_type.dart
  • packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/copy_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/delete_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/edit_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/flag_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/mam_widgets.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/mark_unread_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/message_action.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/message_actions_modal.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/moderated_message_actions_modal.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/pin_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/reply_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/resend_message_button.dart
  • packages/stream_chat_flutter/lib/src/message_actions_modal/thread_reply_button.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/options/stream_file_picker.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/options/stream_gallery_picker.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_bottom_sheet.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_controller.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_option.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_result.dart
  • packages/stream_chat_flutter/lib/src/message_input/dm_checkbox.dart
  • packages/stream_chat_flutter/lib/src/message_input/quoted_message_widget.dart
  • packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart
  • packages/stream_chat_flutter/lib/src/message_input/stream_message_send_button.dart
  • packages/stream_chat_flutter/lib/src/message_list_view/floating_date_divider.dart
  • packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart
  • packages/stream_chat_flutter/lib/src/message_modal/message_action_confirmation_modal.dart
  • packages/stream_chat_flutter/lib/src/message_modal/message_actions_modal.dart
  • packages/stream_chat_flutter/lib/src/message_modal/message_modal.dart
  • packages/stream_chat_flutter/lib/src/message_modal/message_reactions_modal.dart
  • packages/stream_chat_flutter/lib/src/message_modal/moderated_message_actions_modal.dart
  • packages/stream_chat_flutter/lib/src/message_widget/ephemeral_message.dart
  • packages/stream_chat_flutter/lib/src/message_widget/giphy_ephemeral_message.dart
  • packages/stream_chat_flutter/lib/src/message_widget/message_card.dart
  • packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart
  • packages/stream_chat_flutter/lib/src/message_widget/message_widget_content.dart
  • packages/stream_chat_flutter/lib/src/message_widget/message_widget_content_components.dart
💤 Files with no reviewable changes (24)
  • packages/stream_chat/lib/src/permission_type.dart
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_loading.dart
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_slider.dart
  • packages/stream_chat/lib/src/core/api/stream_chat_api.dart
  • packages/stream_chat/test/fixtures/message_to_json.json
  • packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart
  • packages/stream_chat_flutter/lib/src/context_menu_items/context_menu_reaction_picker.dart
  • packages/stream_chat_flutter/lib/src/attachment/attachment_widget_catalog.dart
  • packages/stream_chat_flutter/lib/src/attachment/voice_recording_attachment_playlist.dart
  • packages/stream_chat_flutter/lib/src/context_menu_items/stream_chat_context_menu_item.dart
  • packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart
  • packages/stream_chat/lib/src/core/api/sort_order.g.dart
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_player.dart
  • packages/stream_chat_flutter/lib/src/context_menu_items/download_menu_item.dart
  • packages/stream_chat/test/src/core/api/sort_order_test.dart
  • packages/stream_chat/lib/src/core/api/call_api.dart
  • packages/stream_chat/lib/src/core/models/call_payload.g.dart
  • packages/stream_chat/test/src/core/api/responses_test.dart
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/stream_voice_recording_list_player.dart
  • packages/stream_chat_flutter/lib/src/attachment/builder/voice_recording_attachment_builder/voice_recording_attachment_builder.dart
  • packages/stream_chat/lib/src/core/models/call_payload.dart
  • packages/stream_chat_flutter/lib/src/bottom_sheets/edit_message_sheet.dart
  • packages/stream_chat/test/src/core/api/call_api_test.dart
  • packages/stream_chat/test/src/core/models/call_payload_test.dart
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat/lib/src/core/models/event.g.dart
  • packages/stream_chat/lib/stream_chat.dart
  • packages/stream_chat/example/pubspec.yaml
  • packages/stream_chat/lib/src/core/models/message_delete_scope.g.dart
  • packages/stream_chat/test/src/mocks.dart
  • packages/stream_chat/lib/src/event_type.dart
  • packages/stream_chat/pubspec.yaml
  • packages/stream_chat/lib/src/core/api/message_api.dart
  • packages/stream_chat/lib/src/client/retry_queue.dart
  • packages/stream_chat/lib/src/core/api/responses.dart
  • packages/stream_chat/lib/src/core/models/message_delete_scope.dart
  • packages/stream_chat_flutter/lib/src/message_action/message_action.dart
  • packages/stream_chat/test/src/core/models/message_state_test.dart
  • packages/stream_chat/lib/src/core/models/event.dart
  • packages/stream_chat/test/src/client/retry_queue_test.dart
  • packages/stream_chat/lib/src/core/models/message_state.g.dart
  • packages/stream_chat/lib/src/core/models/message.g.dart
  • packages/stream_chat/test/src/core/models/message_test.dart
  • packages/stream_chat/test/src/db/chat_persistence_client_test.dart
  • packages/stream_chat/CHANGELOG.md
  • packages/stream_chat/test/src/core/api/message_api_test.dart
  • packages/stream_chat/lib/src/db/chat_persistence_client.dart
  • packages/stream_chat/lib/src/core/models/message_delete_scope.freezed.dart
  • packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart
  • packages/stream_chat/lib/src/core/models/member.dart
  • packages/stream_chat_flutter/lib/src/attachment_actions_modal/attachment_actions_modal.dart
  • packages/stream_chat/test/src/core/models/member_test.dart
  • packages/stream_chat_flutter/CHANGELOG.md
  • packages/stream_chat/lib/src/core/models/member.g.dart
  • packages/stream_chat_flutter/example/pubspec.yaml
  • packages/stream_chat/test/src/client/client_test.dart
  • packages/stream_chat/lib/src/core/models/message_state.dart
  • packages/stream_chat/lib/src/client/client.dart
  • packages/stream_chat_flutter/lib/src/localization/translations.dart
  • packages/stream_chat/lib/src/client/channel.dart
  • packages/stream_chat/lib/src/core/models/message_state.freezed.dart
  • packages/stream_chat/lib/src/core/models/message.dart
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message with MessageSendingStatus.failed or MessageSendingStatus.failed_update status, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat/lib/stream_chat.dart
  • packages/stream_chat/example/pubspec.yaml
  • packages/stream_chat/lib/src/core/models/message_delete_scope.g.dart
  • melos.yaml
  • packages/stream_chat/test/src/mocks.dart
  • packages/stream_chat/lib/src/event_type.dart
  • packages/stream_chat/pubspec.yaml
  • packages/stream_chat/lib/src/core/api/message_api.dart
  • packages/stream_chat/lib/src/client/retry_queue.dart
  • packages/stream_chat/lib/src/core/api/responses.dart
  • packages/stream_chat/lib/src/core/models/message_delete_scope.dart
  • packages/stream_chat_flutter/lib/src/message_action/message_action.dart
  • packages/stream_chat/test/src/core/models/message_state_test.dart
  • packages/stream_chat/lib/src/core/models/event.dart
  • packages/stream_chat/test/src/client/retry_queue_test.dart
  • packages/stream_chat/lib/src/core/models/message_state.g.dart
  • packages/stream_chat/lib/src/core/models/message.g.dart
  • packages/stream_chat/test/src/core/models/message_test.dart
  • packages/stream_chat/test/src/db/chat_persistence_client_test.dart
  • packages/stream_chat/CHANGELOG.md
  • packages/stream_chat/test/src/core/api/message_api_test.dart
  • packages/stream_chat/lib/src/db/chat_persistence_client.dart
  • packages/stream_chat/lib/src/core/models/message_delete_scope.freezed.dart
  • packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart
  • packages/stream_chat/lib/src/core/models/member.dart
  • packages/stream_chat_flutter/lib/src/attachment_actions_modal/attachment_actions_modal.dart
  • packages/stream_chat/test/src/core/models/member_test.dart
  • packages/stream_chat_flutter/CHANGELOG.md
  • packages/stream_chat/lib/src/core/models/member.g.dart
  • packages/stream_chat_flutter/example/pubspec.yaml
  • packages/stream_chat/test/src/client/client_test.dart
  • packages/stream_chat/lib/src/core/models/message_state.dart
  • packages/stream_chat/lib/src/client/client.dart
  • packages/stream_chat/lib/src/core/util/message_rules.dart
  • packages/stream_chat_flutter/lib/src/localization/translations.dart
  • packages/stream_chat/lib/src/client/channel.dart
  • packages/stream_chat/lib/src/core/models/message_state.freezed.dart
  • packages/stream_chat/lib/src/core/models/message.dart
📚 Learning: 2025-08-08T14:27:59.621Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2348
File: packages/stream_chat_flutter_core/lib/src/stream_channel.dart:383-406
Timestamp: 2025-08-08T14:27:59.621Z
Learning: In stream_chat_flutter_core/lib/src/stream_channel.dart, threads (replies) do not support around-anchor loading. Thread replies are fetched as: initial latest page via StreamChannelState.getReplies(), and further pagination via StreamChannelState.queryReplies(parentId, direction: top|bottom). Anchored loads apply only to channel messages, not to threads.

Applied to files:

  • packages/stream_chat/pubspec.yaml
  • packages/stream_chat_flutter/CHANGELOG.md
  • packages/stream_chat/lib/src/client/channel.dart
🪛 LanguageTool
migrations/v10-migration.md

[style] ~263-~263: Try using a synonym here to strengthen your writing.
Context: ...Important:* > - The builder pattern gives you access to default options, allowing mor...

(GIVE_PROVIDE)


[grammar] ~900-~900: Use a hyphen to join words.
Context: ...eleteScopeparameter - ✅ Update pattern matching callbacks to handleMessageDel...

(QB_NEW_EN_HYPHEN)


[grammar] ~902-~902: Use a hyphen to join words.
Context: ...eMessageForMe` methods - ✅ Use new state checking methods for delete-for-me opera...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
migrations/v10-migration.md

87-87: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


222-222: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


232-232: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test
  • GitHub Check: build (ios)
  • GitHub Check: build (android)

/// This builder is used when a message contains a poll.
/// {@endtemplate}
class PollAttachmentBuilder extends StreamAttachmentWidgetBuilder {
/// {@macro urlAttachmentBuilder}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the documentation macro reference.

The documentation references {@macro urlAttachmentBuilder} but should reference {@macro pollAttachmentBuilder} to match the template defined at line 7.

Apply this diff to fix the macro reference:

-  /// {@macro urlAttachmentBuilder}
+  /// {@macro pollAttachmentBuilder}
📝 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
/// {@macro urlAttachmentBuilder}
/// {@macro pollAttachmentBuilder}
🤖 Prompt for AI Agents
In
packages/stream_chat_flutter/lib/src/attachment/builder/poll_attachment_builder.dart
around line 13, the documentation macro reference is incorrect: it uses {@macro
urlAttachmentBuilder} but the template defined at line 7 is
pollAttachmentBuilder; update the macro reference to {@macro
pollAttachmentBuilder} so the Dartdoc links to the correct template.

List<String>? allowedExtensions,
Function(FilePickerStatus)? onFileLoading,
bool allowCompression = true,
int compressionQuality = 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Document the compressionQuality parameter semantics.

The new compressionQuality parameter lacks documentation, making its semantics ambiguous:

  • What does a value of 0 represent? (no compression, minimum quality, or something else?)
  • What is the valid range? (0-100, 0-1, or other?)
  • How does the value map to compression behavior?

This is critical for implementers of this abstract class and consumers of the API to use it correctly.

Add inline documentation to clarify the parameter:

   /// Pick a file from the device.
   Future<Attachment?> pickFile({
     String? dialogTitle,
     String? initialDirectory,
     FileType type = FileType.any,
     List<String>? allowedExtensions,
     Function(FilePickerStatus)? onFileLoading,
+    /// The compression quality to apply to the picked file.
+    /// Valid range is 0-100, where:
+    /// - 0: no compression (original quality)
+    /// - 100: maximum compression (lowest quality)
+    /// Defaults to 0 (no compression).
     int compressionQuality = 0,
     bool withData = true,
     bool withReadStream = false,
     bool lockParentWindow = true,
   }) {

Please verify the actual semantics by checking the implementation in the HTML and IO handler files:


🏁 Script executed:

#!/bin/bash
# Find and examine how compressionQuality is used in implementations
rg -A 10 -B 2 'compressionQuality' packages/stream_chat_flutter/lib/src/attachment/handler/

Length of output: 7452


Good news! I found the official file_picker package documentation. The compressionQuality parameter defines the compression quality percentage to use when compressing images, with values ranging from 0 (no compression) to 100.

However, there's a critical issue with the documentation suggested in the original review comment. The phrasing "100: maximum compression (lowest quality)" is misleading. In typical usage semantics, a higher "quality" number usually means better quality, not maximum compression. The file_picker documentation doesn't explicitly clarify whether the scale represents "quality level" (higher = better) or "compression ratio" (higher = more compressed). This ambiguity needs to be resolved.

Let me verify the actual behavior by checking if there are any code comments or tests in the repository that clarify this:

Based on my verification, I've found a critical issue with the suggested documentation in the original review comment:

The file_picker documentation states the compressionQuality value ranges from 0 (no compression) to 100. However, the suggested documentation in the review comment is backwards. In related Flutter packages, 0 means compress for small size, and 100 means compress for max quality — meaning higher numbers represent better quality, not maximum compression.

The original review suggested documenting compressionQuality as:

  • 0: no compression (original quality)
  • 100: maximum compression (lowest quality)

This is incorrect. The correct semantics should be:

  • 0: no compression (original quality)
  • 100: maximum quality (least compression)

Add corrected parameter documentation to clarify compressionQuality semantics.

The parameter lacks documentation, and the suggested values were reversed. The valid range is 0 (no compression) to 100, where higher values represent better quality, not maximum compression.

   /// Pick a file from the device.
   Future<Attachment?> pickFile({
     String? dialogTitle,
     String? initialDirectory,
     FileType type = FileType.any,
     List<String>? allowedExtensions,
     Function(FilePickerStatus)? onFileLoading,
+    /// The compression quality to apply to the picked file.
+    /// Valid range is 0–100, where:
+    /// - 0: no compression (original quality)
+    /// - 100: maximum quality (least compression)
+    /// Only affects image compression on mobile platforms.
+    /// Defaults to 0 (no compression).
     int compressionQuality = 0,
     bool withData = true,
     bool withReadStream = false,
     bool lockParentWindow = true,
   }) {
📝 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
int compressionQuality = 0,
/// The compression quality to apply to the picked file.
/// Valid range is 0–100, where:
/// - 0: no compression (original quality)
/// - 100: maximum quality (least compression)
/// Only affects image compression on mobile platforms.
/// Defaults to 0 (no compression).
int compressionQuality = 0,
🤖 Prompt for AI Agents
In
packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_base.dart
around line 34, the parameter documentation for compressionQuality is missing
and previous wording reversed semantics; update the doc comment for the int
compressionQuality parameter to state the valid range is 0–100 and that higher
values mean better image quality (less compression) while 0 means no
compression/original quality, replacing any text that implied 100 means maximum
compression/lowest quality.

Comment on lines +25 to +64
/// Resolves casted or changed poll vote events into more specific
/// `pollAnswerCasted` events for easier downstream state handling.
///
/// Applies when:
/// - `event.type` is `pollVoteCasted` or `pollVoteChanged`, and
/// - `event.pollVote?.isAnswer == true`
///
/// Returns a modified event with type `pollAnswerCasted`,
/// or `null` if not applicable.
Event? pollAnswerCastedResolver(Event event) {
final validTypes = {EventType.pollVoteCasted, EventType.pollVoteChanged};
if (!validTypes.contains(event.type)) return null;

final pollVote = event.pollVote;
if (pollVote?.isAnswer == false) return null;

// If the event is a poll vote casted or changed and it's an answer
// we can resolve it to a poll answer casted event.
return event.copyWith(type: EventType.pollAnswerCasted);
}

/// Resolves removed poll vote events into more specific
/// `pollAnswerRemoved` events for easier downstream state handling.
///
/// Applies when:
/// - `event.type` is `pollVoteRemoved`, and
/// - `event.pollVote?.isAnswer == true`
///
/// Returns a modified event with type `pollAnswerRemoved`,
/// or `null` if not applicable.
Event? pollAnswerRemovedResolver(Event event) {
if (event.type != EventType.pollVoteRemoved) return null;

final pollVote = event.pollVote;
if (pollVote?.isAnswer == false) return null;

// If the event is a poll vote removed and it's an answer
// we can resolve it to a poll answer removed event.
return event.copyWith(type: EventType.pollAnswerRemoved);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard poll vote resolvers against null pollVote to avoid misclassifying events

In both pollAnswerCastedResolver and pollAnswerRemovedResolver you only reject the event when pollVote?.isAnswer == false. If pollVote is null, the condition is false and you still convert the event, even though there is no vote payload:

final pollVote = event.pollVote;
if (pollVote?.isAnswer == false) return null;
// null pollVote falls through and becomes pollAnswerCasted/Removed
return event.copyWith(...);

Safer is to require isAnswer == true explicitly:

 Event? pollAnswerCastedResolver(Event event) {
   final validTypes = {EventType.pollVoteCasted, EventType.pollVoteChanged};
   if (!validTypes.contains(event.type)) return null;

   final pollVote = event.pollVote;
-  if (pollVote?.isAnswer == false) return null;
+  if (pollVote?.isAnswer != true) return null;

   return event.copyWith(type: EventType.pollAnswerCasted);
 }

 Event? pollAnswerRemovedResolver(Event event) {
   if (event.type != EventType.pollVoteRemoved) return null;

   final pollVote = event.pollVote;
-  if (pollVote?.isAnswer == false) return null;
+  if (pollVote?.isAnswer != true) return null;

   return event.copyWith(type: EventType.pollAnswerRemoved);
 }

This prevents spurious pollAnswer* events if the backend ever emits vote events without a pollVote payload.

🤖 Prompt for AI Agents
In packages/stream_chat/lib/src/client/event_resolvers.dart around lines 25 to
64, the resolvers currently only bail out when pollVote?.isAnswer == false which
allows a null pollVote to fall through and incorrectly convert events; change
the guards to explicitly require pollVote?.isAnswer == true (i.e. return null if
pollVote is null or isAnswer is not true) in both pollAnswerCastedResolver and
pollAnswerRemovedResolver so only events with a present pollVote marked as an
answer are converted to pollAnswerCasted/pollAnswerRemoved.

Comment on lines +65 to +89
// region Standalone upload methods

/// Uploads an image file to the CDN.
///
/// Upload progress can be tracked using [onProgress], and the operation can
/// be cancelled using [cancelToken].
///
/// Returns a [UploadImageResponse] once uploaded successfully.
Future<UploadImageResponse> uploadImage(
AttachmentFile image, {
ProgressCallback? onSendProgress,
CancelToken? cancelToken,
});

/// Uploads a file to the CDN.
///
/// Upload progress can be tracked using [onProgress], and the operation can
/// be cancelled using [cancelToken].
///
/// Returns a [UploadFileResponse] once uploaded successfully.
Future<UploadFileResponse> uploadFile(
AttachmentFile file, {
ProgressCallback? onSendProgress,
CancelToken? cancelToken,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix doc comment parameter name for standalone upload methods.

The new uploadImage/uploadFile docs mention [onProgress], but the actual parameter is onSendProgress (consistent with the channel-scoped methods). This is only a documentation mismatch but can be confusing when using IDE tooling.

You can fix this by updating the references in the doc comments:

-  /// Upload progress can be tracked using [onProgress], and the operation can
+  /// Upload progress can be tracked using [onSendProgress], and the operation can
@@
-  /// Upload progress can be tracked using [onProgress], and the operation can
+  /// Upload progress can be tracked using [onSendProgress], and the operation can

No changes are needed in the implementations; the new CDN endpoints and response types look correct.

Also applies to: 191-221

🤖 Prompt for AI Agents
In packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart around
lines 65-89 (and similarly update lines 191-221), the doc comments reference
[onProgress] which does not match the actual parameter name onSendProgress;
update the doc comments to refer to [onSendProgress] (and any inline mentions of
onProgress) so the parameter name in the documentation matches the method
signature and IDE tooling links correctly.

Comment on lines +825 to +826
/// Model response for [StreamChatClient.updateDraft] api call
@JsonSerializable(createToJson: false)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the documentation comment.

The doc comment references updateDraft but the class is GetActiveLiveLocationsResponse.

Apply this diff to fix the documentation:

-/// Model response for [StreamChatClient.updateDraft] api call
+/// Model response for [StreamChatClient.getActiveLiveLocations] api call
 @JsonSerializable(createToJson: false)
 class GetActiveLiveLocationsResponse extends _BaseResponse {
🤖 Prompt for AI Agents
In packages/stream_chat/lib/src/core/api/responses.dart around lines 825 to 826,
the documentation comment incorrectly references updateDraft for this class;
update the doc comment to reference GetActiveLiveLocationsResponse (or a neutral
description of the response) so it accurately documents the class
purpose—replace "Model response for [StreamChatClient.updateDraft] api call"
with a correct description mentioning GetActiveLiveLocationsResponse (or the API
call it represents) and ensure spelling/casing matches project style.

Comment on lines +87 to +103
/// Returns true if the live location is still active (end_at > now)
bool get isActive {
final endAt = this.endAt;
if (endAt == null) return false;

return endAt.isAfter(DateTime.now());
}

/// Returns true if the live location is expired (end_at <= now)
bool get isExpired => !isActive;

/// Returns true if this is a live location (has end_at)
bool get isLive => endAt != null;

/// Returns true if this is a static location (no end_at)
bool get isStatic => endAt == null;

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

isExpired incorrectly flags static locations as expired

isExpired is currently implemented as !isActive, and isActive returns false when endAt is null. That means static locations (no endAt) will be treated as expired, which contradicts the docs (“live location is expired (end_at <= now)”) and likely semantics where static locations are neither “active live” nor “expired”.

Consider constraining expiry to live locations only, e.g.:

bool get isExpired => endAt != null && !isActive;

This keeps isLive / isStatic orthogonal and avoids misclassifying static locations as expired.

🤖 Prompt for AI Agents
In packages/stream_chat/lib/src/core/models/location.dart around lines 87 to
103, isExpired is implemented as !isActive which causes static locations (endAt
== null) to be marked expired; change the getter so it only considers live
locations expired by requiring endAt != null and that the end time is not after
now (i.e., return true only when there is an endAt and it is <= now) — update
the isExpired getter accordingly so static locations are not flagged expired.

Comment on lines 288 to +393
test(
'MessageState.softDeletingFailed should create a MessageFailed instance with DeletingFailed state and not hard deleting',
'MessageState.partialUpdatingFailed should create a MessageFailed instance with UpdatingFailed state',
() {
final messageState = MessageState.partialUpdatingFailed(
skipEnrichUrl: false,
);
expect(messageState, isA<MessageFailed>());
expect(
(messageState as MessageFailed).state,
isA<PartialUpdatingFailed>(),
);
},
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix partialUpdatingFailed test description to match the actual state

The partialUpdatingFailed test description says:

'MessageState.partialUpdatingFailed should create a MessageFailed instance with UpdatingFailed state'

but the assertion correctly checks for isA<PartialUpdatingFailed>():

expect(
  (messageState as MessageFailed).state,
  isA<PartialUpdatingFailed>(),
);

To avoid confusion for future readers, it would be better to update the description to mention PartialUpdatingFailed instead of UpdatingFailed.

🤖 Prompt for AI Agents
packages/stream_chat/test/src/core/models/message_state_test.dart around lines
381 to 393: the test description incorrectly says "UpdatingFailed" while the
assertions check for PartialUpdatingFailed; update the test description string
to mention "PartialUpdatingFailed" so it matches the actual asserted state and
avoids confusion for future readers.

@tahaJemmali
Copy link

Hello, Taha — big fan.
Quick note: in channel.dartChannelClientStatedispose(), adding .truncate() will clear accumulated channel messages and fix the memory heap issue many are facing.
Thanks!

# Conflicts:
#	packages/stream_chat/CHANGELOG.md
#	packages/stream_chat_flutter/CHANGELOG.md
#	packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_idle_dark.png
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_idle_light.png
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playing_dark.png
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playing_light.png
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playlist_dark.png
#	packages/stream_chat_flutter/test/src/attachment/goldens/ci/stream_voice_recording_attachment_playlist_light.png
#	packages/stream_chat_flutter/test/src/avatars/goldens/ci/gradient_avatar_issue_2369.png
#	packages/stream_chat_flutter/test/src/bottom_sheets/goldens/ci/edit_message_sheet_0.png
#	packages/stream_chat_flutter/test/src/bottom_sheets/goldens/ci/error_alert_sheet_0.png
#	packages/stream_chat_flutter/test/src/channel/goldens/ci/channel_header_bottom_widget.png
#	packages/stream_chat_flutter/test/src/context_menu_items/goldens/ci/download_menu_item_0.png
#	packages/stream_chat_flutter/test/src/context_menu_items/goldens/ci/stream_chat_context_menu_item_0.png
#	packages/stream_chat_flutter/test/src/dialogs/goldens/ci/confirmation_dialog_0.png
#	packages/stream_chat_flutter/test/src/dialogs/goldens/ci/delete_message_dialog_0.png
#	packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_0.png
#	packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_1.png
#	packages/stream_chat_flutter/test/src/dialogs/goldens/ci/message_dialog_2.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_hold_dark.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_hold_light.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_locked_dark.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_locked_light.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_stopped_dark.png
#	packages/stream_chat_flutter/test/src/message_input/audio_recorder/goldens/ci/stream_audio_recorder_button_recording_stopped_light.png
#	packages/stream_chat_flutter/test/src/message_input/goldens/ci/countdown_button_0.png
#	packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_custom.png
#	packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_dark.png
#	packages/stream_chat_flutter/test/src/message_widget/goldens/ci/deleted_message_light.png
#	packages/stream_chat_flutter/test/src/misc/goldens/ci/stream_timestamp_light.png
#	packages/stream_chat_flutter/test/src/misc/goldens/ci/system_message_dark.png
#	packages/stream_chat_flutter/test/src/misc/goldens/ci/system_message_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_error_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_error_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_option_reorderable_list_view_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_error_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_error_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/poll_question_text_field_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/creator/goldens/ci/stream_poll_creator_full_screen_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_error.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_option_reorderable_list_view_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_error.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/poll_question_text_field_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_creator_full_screen_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_options_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_options_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_with_show_all_dark.png
#	packages/stream_chat_flutter/test/src/poll/goldens/ci/stream_poll_results_dialog_with_show_all_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_with_initial_value_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_add_comment_dialog_with_initial_value_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_end_vote_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_long_question_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_long_question_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_all_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_all_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_disabled_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_disabled_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_limited_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_limited_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_unique_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_header_subtitle_voting_mode_unique_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_with_initial_option_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/poll_suggest_option_dialog_with_initial_option_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_closed_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_closed_light.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_dark.png
#	packages/stream_chat_flutter/test/src/poll/interactor/goldens/ci/stream_poll_interactor_light.png
#	packages/stream_chat_flutter/test/src/scroll_view/draft_scroll_view/goldens/ci/stream_draft_list_tile_dark.png
#	packages/stream_chat_flutter/test/src/scroll_view/draft_scroll_view/goldens/ci/stream_draft_list_tile_light.png
#	packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_thread_list_tile_dark.png
#	packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_thread_list_tile_light.png
#	packages/stream_chat_flutter/test/src/scroll_view/thread_scroll_view/goldens/ci/stream_unread_threads_banner_light.png
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

⚠️ Database Entity Files Modified

The following database entity files have been modified in this PR:

packages/stream_chat_persistence/lib/src/entity/entity.dart
packages/stream_chat_persistence/lib/src/entity/locations.dart
packages/stream_chat_persistence/lib/src/entity/members.dart
packages/stream_chat_persistence/lib/src/entity/messages.dart
packages/stream_chat_persistence/lib/src/entity/pinned_message_reactions.dart
packages/stream_chat_persistence/lib/src/entity/reactions.dart

📝 Remember to:

  1. Update database version in db/drift_chat_database.dart.
  2. Update entity schema tests if necessary.

Note: This comment is automatically generated by the CI workflow.

Copy link
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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart (1)

419-419: Address the TODO: refactor to callback-based pattern.

The TODO comment indicates the current onTap implementation should be replaced with a callback-based approach for better architecture.

Do you want me to help design the callback-based implementation or open an issue to track this technical debt?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2a117b0 and 302ade6.

📒 Files selected for processing (4)
  • melos.yaml (4 hunks)
  • packages/stream_chat/CHANGELOG.md (7 hunks)
  • packages/stream_chat_flutter/CHANGELOG.md (7 hunks)
  • packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/stream_chat/CHANGELOG.md
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message with MessageSendingStatus.failed or MessageSendingStatus.failed_update status, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • melos.yaml
  • packages/stream_chat_flutter/CHANGELOG.md
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat_flutter/CHANGELOG.md
📚 Learning: 2025-08-08T14:27:59.621Z
Learnt from: xsahil03x
Repo: GetStream/stream-chat-flutter PR: 2348
File: packages/stream_chat_flutter_core/lib/src/stream_channel.dart:383-406
Timestamp: 2025-08-08T14:27:59.621Z
Learning: In stream_chat_flutter_core/lib/src/stream_channel.dart, threads (replies) do not support around-anchor loading. Thread replies are fetched as: initial latest page via StreamChannelState.getReplies(), and further pagination via StreamChannelState.queryReplies(parentId, direction: top|bottom). Anchored loads apply only to channel messages, not to threads.

Applied to files:

  • packages/stream_chat_flutter/CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: update_goldens
  • GitHub Check: stream_chat_localizations
  • GitHub Check: build (ios)
  • GitHub Check: analyze_legacy_versions
  • GitHub Check: test
  • GitHub Check: build (android)
  • GitHub Check: stream_chat_flutter
  • GitHub Check: stream_chat_flutter_core
  • GitHub Check: stream_chat_persistence
🔇 Additional comments (5)
packages/stream_chat_flutter/CHANGELOG.md (1)

8-77: Significant discrepancy between the AI-generated summary and the documented changelog entries.

The enriched AI summary describes substantial changes including live location sharing, scoped message deletion (delete-for-me), Reaction API refactors, EventController with resolvers, CDN upload/remove endpoints, and extensive model/serialization updates. However, the v10.0.0-beta.9 changelog section only documents reaction indicator customizations and two breaking changes.

Additionally, the PR objective references a specific memory heap fix (adding .truncate() to channel.dart) recommended by a reviewer, which is not reflected in the changelog.

Please verify:

  1. Whether all substantial changes described in the AI summary should be documented in the beta.9 changelog
  2. Whether the memory heap fix warrants a changelog entry in the "Fixed" section
  3. If the changelog is intentionally minimal or if major feature entries are missing

If changes are confirmed but not yet documented, consider adding entries for:

  • Location/live location features
  • Message deletion scope refactoring
  • Event type expansions
  • Attachment file uploader API enhancements
  • Memory heap optimization
melos.yaml (2)

87-91: Stream Chat 10.0.0-beta.9 is reasonably stable for pre-release.

All five Stream Chat packages are consistently updated to 10.0.0-beta.9. This beta includes targeted fixes (Location.endAt UTC conversion, cached message clearing for offline channels, UI/core fixes) and no critical blockers have been reported. The known compatibility issues (Flutter 3.22, transitive dependency conflicts) are pre-existing and unrelated to the package version pins themselves.


27-99: No version conflicts or incompatible transitive dependencies detected.

The new geolocation, mapping, and Stream Chat packages integrate cleanly with existing dependencies. Verification confirms: (1) version constraints are consistent across melos.yaml and all workspace pubspecs; (2) geolocator and device_info_plus share no overlapping transitive dependencies; (3) platform-specific implementations are properly isolated. The current dependency set appears sound. If additional validation is needed, run melos bootstrap --validate in your environment to confirm resolution against the latest pub.dev versions.

packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart (2)

125-132: LGTM! Context menu builder correctly captures current state.

The context menu builder properly captures the current page index and retrieves the corresponding media attachment when the menu is shown.


360-370: LGTM! Context menu correctly references attachment from outer scope.

The context menu builder properly uses currentAttachmentPackage from the enclosing itemBuilder scope.

# List of all the dependencies used in the project.
dependencies:
async: ^2.11.0
avatar_glow: ^3.0.0
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

geolocator 13.0.0 Flutter known issues security concerns

💡 Result:

Short summary — geolocator 13.0.0 (Flutter)

  • What changed in 13.0.0

    • Breaking changes: deprecates getCurrentPosition parameters (desiredAccuracy, forceAndroidLocationManager, timeLimit) in favor of a LocationSettings class; exposes WebSettings; updated federated subpackage deps (android/apple/web/windows/platform_interface). [1]
  • Known functional issues (reported & fixed soon after)

    • 13.0.1/13.0.2/13.0.3 quickly followed to fix compilation/example issues (13.0.1 fixed illegal reference to dart:js_interop on non‑web builds; other 13.x releases updated dependencies and example configs). If you hit build/compiler issues, upgrade to the patched 13.x or newer. [1]
  • Security vulnerabilities to be aware of

    • There is a public CVE (CVE‑2024‑52443) for a WordPress plugin named “Geolocator” (PHP object‑injection / deserialization) — this affects that WordPress plugin (versions ≤1.1), not the Flutter geolocator package. The Flutter geolocator package has no CVE record shown by the public databases for 13.0.0. Do not conflate the two projects. [2][3]
  • Other security/privacy notes (general, relevant to any location plugin)

    • Browser geolocation requires secure origins (HTTPS); geolocation APIs are deprecated on insecure origins. For web builds, serve over HTTPS. [4]
    • Review platform permission settings (foreground vs background location), Android 13+/iOS 14+ permission behavior, and limit how long/location granularity is requested in production apps. Also audit third‑party subpackages (geolocator_android, geolocator_apple, geolocator_web) for updates. [1]
  • Recommendation

    • If you use 13.0.0: upgrade to the latest stable geolocator (14.x as of the package page) or at least 13.0.4+ (which contains quick fixes) and test builds on all target platforms. Audit your app’s permission requests and ensure web builds are served over HTTPS. [1]

Sources

  • geolocator changelog (pub.dev). [1]
  • NVD / CVE records and aggregators for CVE‑2024‑52443 (WordPress Geolocator plugin). [2][3]
  • Chromium/DevTools note on geolocation requiring secure origins (HTTPS). [4]

If you want, I can:

  • check the exact latest geolocator version now and provide upgrade guidance for your pubspec, or
  • scan your project for usages of the deprecated getCurrentPosition parameters and produce a small migration patch.

🌐 Web query:

flutter_map 8.1.1 stability production usage

💡 Result:

Short answer: flutter_map 8.1.1 is a bug‑fix release (published 2025‑03‑08) that addresses an infinite‑loop bug with polygon labels on rotated maps; it’s part of an actively maintained 8.x line and is generally fine for production if you pin and test it in your app. [1][2][3]

Details & recommendation:

  • Release: 8.1.1 — 2025‑03‑08; changelog lists the polygon‑label infinite‑loop fix. Test your polygon/rotation code path. [1]
  • Maintenance: the project is community‑maintained with frequent 8.x fixes/patches (see repo releases). Keep an eye on later 8.x bugfixes (e.g., 8.2.x) and update when appropriate. [2][3]
  • Practical advice: pin the exact package version in pubspec.yaml, run your full test matrix (Android/iOS/web, device/OS versions you support), and check upstream issues for any regressions specific to your use (e.g., tile caching, vector tile plugins). If you rely on related plugins (tile caching, vector tiles), verify compatibility with their versions too.

Sources:
[1] flutter_map changelog (pub.dev) — 8.1.1 entry.
[2] fleaflet/flutter_map GitHub releases.
[3] flutter_map docs (fleaflet).


🌐 Web query:

avatar_glow flutter package security maintenance

💡 Result:

Short summary

  • Current package: avatar_glow — latest published release on pub.dev is v3.0.1. [1]
  • Source: GitHub repo apgapg/avatar_glow (repository and live demo linked from pub.dev). [1][3]
  • Maintenance signals: recent pub.dev metadata shows infrequent updates (latest release published ~24 months ago on pub.dev listings) and a small issue count on the repo — active but low-maintenance. [1][2]
  • Security posture: no public CVEs or security advisories listed on pub.dev or Libraries.io; package is MIT-licensed, has no external native/unsafe dependencies (pure Flutter widget), so attack surface is small — but no formal audit found. [1][2]
  • Practical recommendations:
    • Pin the package version in pubspec.yaml (avoid floating ranges) and vendor or audit the code if you rely on it in production. [1]
    • Review the GitHub issues/PRs before upgrading; consider using the GitHub repo directly if you need an unpushed fix. [1][3]
    • If you need long-term maintenance guarantees, either fork and maintain the widget in your repo or implement the simple glow effect yourself (widget is small). [2][3]

Sources
[1] pub.dev/avatar_glow package page (metadata, versions, repo link).
[2] Libraries.io / pub listing for avatar_glow (package metadata, license, maintenance info).
[3] GitHub repository referenced by package (apgapg/avatar_glow).


🌐 Web query:

flutter_map_animations latlong2 compatibility issues

💡 Result:

Short answer — common compatibility causes and fixes

  • Root cause: flutter_map and many related plugins (including flutter_map_animations) use the LatLng type from the latlong2 package; mismatched versions or having multiple LatLng types (from latlong, latlong2, google_maps_flutter, etc.) produce type errors. (docs.fleaflet.dev)

  • Quick checks/fixes:

    1. Add latlong2 to your pubspec (same major version expected by your flutter_map/flutter_map_animations). Example: flutter pub add latlong2. (docs.fleaflet.dev)
    2. Import the correct symbol where used: import 'package:latlong2/latlong.dart'; or import it with an alias if another LatLng exists: import 'package:latlong2/latlong.dart' as ll2; then use ll2.LatLng(...). This resolves ambiguous/assignability errors. (stackoverflow.com)
    3. Make sure flutter_map_animations and flutter_map versions target the same latlong2 major version — if not, upgrade/downgrade or add a dependency_override for latlong2 (temporarily) so all packages use the same package version. Then run flutter clean && flutter pub get. (docs.fleaflet.dev)
    4. If upgrading to flutter_map v5+ or other major releases, read migration notes — latlong2 had updates (const constructors, version bumps) that can cause small breaking changes. Apply suggested migration fixes (dart fix, update constructors/usages). (docs.fleaflet.dev)
  • If you still get errors: inspect pub deps (flutter pub deps --style=compact) to find multiple latlong/LatLng providers; remove the old latlong package or unify versions. Stack Overflow and flutter_map docs show this is the usual resolution. (stackoverflow.com)

If you want, tell me the pubspec.yaml and exact error message and I’ll give step‑by‑step edits.

Citations:


Upgrade geolocator to version 13.0.4 or later; other new dependencies are stable.

The addition of avatar_glow, flutter_map, flutter_map_animations, and latlong2 aligns well with the live location sharing feature and poses no known security or stability concerns. However, geolocator 13.0.0 has known breaking changes and required multiple bugfix patches (13.0.1–13.0.3). Upgrade to at least 13.0.4+ or the latest stable version (14.x) to avoid compilation issues and benefit from critical fixes. Also ensure web builds are served over HTTPS and audit your app's location permission scopes (foreground vs. background, especially for Android 13+ and iOS 14+).

Also applies to: 47-48, 56-56, 66-66

🤖 Prompt for AI Agents
In melos.yaml around line 28 (also applies to lines 47-48, 56, and 66), the
project references geolocator 13.0.0 which has known breaking changes and
required bugfixes; update the geolocator dependency entries to at least 13.0.4
or preferably the latest stable 14.x release, ensure the version constraint
reflects a minimum of 13.0.4 (e.g., ^13.0.4 or ^14.0.0), and run pub get to
verify resolution; additionally confirm your web builds are served over HTTPS
and audit Android/iOS location permission scopes (foreground vs background) for
Android 13+ and iOS 14+ to match the updated geolocator behavior.

Comment on lines +420 to +430
onTap: (action) async {
if (action is! CustomMessageAction) return;
final attachment = action.extraData[_attachmentKey] as Attachment?;
if (attachment == null) return;

final popped = await Navigator.of(context).maybePop();
if (popped) {
final handler = StreamAttachmentHandler.instance;
return handler.downloadAttachment(attachment).ignore();
}
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "*.dart" | xargs grep -l "class StreamAttachmentHandler" | head -5

Repository: GetStream/stream-chat-flutter

Length of output: 352


🏁 Script executed:

cat -n packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_base.dart | head -150

Repository: GetStream/stream-chat-flutter

Length of output: 3178


🏁 Script executed:

cat -n packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart

Repository: GetStream/stream-chat-flutter

Length of output: 8489


🏁 Script executed:

grep -rn "downloadAttachmentData" packages/stream_chat_flutter/lib/src/attachment/handler/ --include="*.dart" -A 20 | head -80

Repository: GetStream/stream-chat-flutter

Length of output: 9142


🏁 Script executed:

cat -n packages/stream_chat_flutter/lib/src/attachment/handler/common.dart | head -150

Repository: GetStream/stream-chat-flutter

Length of output: 3266


Add error handling for download failures instead of silently suppressing them.

The .ignore() call at line 428 suppresses all errors from the download operation. Since StreamAttachmentHandler.downloadAttachment() has no internal error handling (file I/O and network operations can fail), any download or save failure will be silently swallowed, leaving users without feedback. Handle the error explicitly with logging or user-facing notifications.

🤖 Prompt for AI Agents
In
packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart
around lines 420 to 430, the call to
handler.downloadAttachment(attachment).ignore() swallows any errors; replace it
with an awaited try/catch that handles failures: await the download call inside
a try block, catch exceptions, log the error (use existing logger or debugPrint)
and surface a user-facing notification (e.g.,
ScaffoldMessenger.of(context).showSnackBar or the package's error UI) with a
clear message, and ensure the catch does not rethrow unless needed.

xsahil03x and others added 2 commits December 3, 2025 14:57
Corrects the version number from `10.0-beta.10` to `10.0.0-beta.10` in the `stream_chat_localizations` changelog.
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.

4 participants