Unify MessageComposer state and expose read-only StateFlows on ViewModels#6279
Unify MessageComposer state and expose read-only StateFlows on ViewModels#6279
MessageComposer state and expose read-only StateFlows on ViewModels#6279Conversation
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
WalkthroughThis PR refactors the message composer architecture by consolidating multiple public mutable state flows (cooldown timer, validation errors, suggestions, message mode, capabilities, and actions) into a single read-only Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment Tip CodeRabbit can generate a title for your PR based on the changes with custom instructions.Set the |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Line 7082: Update the UNRELEASED CHANGELOG under the
stream-chat-android-compose → Changed section to document that getMessageInput()
now returns a read-only StateFlow (not MutableStateFlow), which prevents direct
assignment via messageInput.value; note the migration path instructing consumers
to call the provided setMessageInput(...) API instead of mutating
messageInput.value and mention this is an intentional API shape change for
immutability.
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt`:
- Around line 927-928: The controller is exposing its internal MutableSet
(selectedMentions) into public state, causing later mutations (+= and clear())
to break snapshot immutability; change the _state.update call in
MessageComposerController to publish an immutable copy (e.g.,
selectedMentions.toSet() or HashSet(selectedMentions)) instead of the live
MutableSet, and when filterMentions() clears the backing set call _state.update
{ it.copy(selectedMentions = emptySet()) } (or publish an explicit empty
snapshot) so consumers never observe the mutable backing instance.
- Around line 533-540: The current setMessageMode publishes the new mode only
after saveDraftMessage(prev) which can suspend, causing races; change the order
so setMessageMode first updates/publishes the new mode via _state.update {
it.copy(messageMode = messageMode) } (while still capturing previousMode for the
draft), then call saveDraftMessage(previousMode) and finally
fetchDraftMessage(messageMode); update the implementation in setMessageMode (and
keep isSameMessageMode check) to ensure the new mode is visible immediately and
avoid stale reads from concurrent setMessageMode calls.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 89036ccf-92f2-472f-8a2f-017b0bfa8566
📒 Files selected for processing (9)
stream-chat-android-compose/api/stream-chat-android-compose.apistream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/AttachmentPickerMenu.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/messages/MessageComposerViewModel.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/messages/MessageComposerViewModelTest.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.ktstream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/chat/ChatFragment.ktstream-chat-android-ui-components/api/stream-chat-android-ui-components.apistream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/messages/MessageComposerViewModel.ktstream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/messages/MessageComposerViewModelTest.kt
...n/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt
Show resolved
Hide resolved
...n/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt
Outdated
Show resolved
Hide resolved
… the single source of truth for UI properties including `cooldownTimer`, `validationErrors`, `mentionSuggestions`, `commandSuggestions`, and `messageMode`.
…by exposing immutable `StateFlow` instead of `MutableStateFlow`.
…t ran, _state.value.messageMode was still the old mode, so overlapping setMessageMode calls could read stale mode.
…te. Further += / clear() changed that object in place, so you lost clear “snapshot” semantics and StateFlow might not emit when only the set contents changed.
74dcd51 to
aeb30b0
Compare
|


Goal
Stop duplicating composer UI in extra flows; expose StateFlow only so state is read through MessageComposerState (and setMessageInput / actions) instead of mutable flows.
Implementation
Breaking: use messageComposerState for those fields; don’t assign messageInput.value — use setMessageInput.
🎨 UI Changes
No intentional visual change.
Testing
Summary by CodeRabbit
Release Notes