Skip to content

feat(UI): rename message input#2642

Open
renefloor wants to merge 13 commits intov10.0.0from
feature/rename-message-input
Open

feat(UI): rename message input#2642
renefloor wants to merge 13 commits intov10.0.0from
feature/rename-message-input

Conversation

@renefloor
Copy link
Copy Markdown
Contributor

@renefloor renefloor commented May 5, 2026

Submit a pull request

CLA

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

Description of the pull request

This renames the StreamMessageInput to StreamMessageComposer and the StreamChatMessageComposer to StreamChatMessageInput.

It also fixes the component builders and the attachment sync.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced refactored message composer component with improved API and design system integration.
  • Updates

    • Updated all examples and documentation to reflect latest message composition component naming.
    • Enhanced component architecture for better customization and consistency.

@renefloor renefloor changed the title Feature/rename message input feat(UI) : rename message input May 5, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Important

Review skipped

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

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

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86164693-7e8f-4580-9de0-be9ab4f8b8e3

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR refactors the message composition architecture by splitting responsibilities between StreamMessageComposer (full-featured, stateless wrapper) and StreamChatMessageInput (new design-system, UI-only). The old StreamChatMessageComposer and StreamMessageInput names are replaced, props structures are updated to support input-level configuration, and all examples, tests, migrations, and documentation are updated to reflect the new naming and component hierarchy.

Changes

Message Composer Redesign

Layer / File(s) Summary
Props & Configuration
packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart
MessageComposerComponentProps drops the message field. MessageComposerInputProps gains input-level config: placeholder, textInputAction, keyboardType, textCapitalization, autofocus, autocorrect, canAlsoSendToChannel, audioRecorderController, feedback, sendVoiceRecordingAutomatically.
New Architecture & Removal
packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_composer.dart, packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_input.dart
StreamChatMessageComposer is removed (456 lines deleted). New StreamChatMessageInput (StatefulWidget) introduced: manages internal StreamMessageInputController, wraps composer in ValueListenableBuilder when audio-recorder present, conditionally shows hold-to-record tooltip/lock via flutter_portal, handles voice-recording gestures (long-press start/finish/cancel, drag-to-lock).
Input Component Rendering
packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input.dart
New StreamMessageComposerInput (StatelessWidget) and DefaultStreamMessageComposerInput added. Default renders audio recording UI conditionally based on props.audioRecorderState, or falls back to core.StreamMessageComposerInputField plus optional DmCheckboxListTile for "also send to channel".
Stateless Composer Wrapper & Integration
packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart
StreamMessageComposer (StatelessWidget) replaces old StreamMessageInput usage as the primary public API. Accepts full configuration, builds MessageComposerProps, and renders custom or default composer. DefaultStreamMessageComposerState refactored to read all config from widget.props instead of direct widget fields. Attachment picker sync now handles both removal and addition.
Public Exports & Wiring
packages/stream_chat_flutter/lib/src/components/message_composer/message_composer.dart, packages/stream_chat_flutter/lib/stream_chat_flutter.dart, packages/stream_chat_flutter/lib/src/keyboard_shortcuts/keysets.dart
Export of stream_chat_message_composer.dart removed, stream_chat_message_input.dart added. Public library barrel removes stream_message_input.dart export, adds stream_message_composer.dart. Keyboard shortcut docs updated to reference StreamMessageComposer.
Examples & Sample Apps
packages/stream_chat_flutter/example/lib/{main,split_view,tutorial_part_*}.dart, packages/stream_chat_localizations/example/lib/{main,add_new_lang,override_lang}.dart, sample_app/lib/pages/{channel_page,new_chat_screen,thread_page}.dart
All example and sample app message-input widgets replaced: StreamMessageInputStreamMessageComposer. Scaffold constness adjusted where needed. Thread composers preserve messageInputController with Message(parentId: parent!.id) wiring.
Tests & Golden Screenshots
packages/stream_chat_flutter/test/src/message_input/message_input_test.dart, docs/docs_screenshots/test/{message_input,voice_recording}/*.dart
Widget tests and screenshot tests updated: StreamMessageInputStreamMessageComposer. Golden test snapshots renamed (stream_message_input_defaultstream_message_composer_default). Voice recording scaffold split: inner input uses StreamMessageComposer, outer composer uses StreamChatMessageInput with audioRecorderController injection. GlobalKey type changed to GlobalKey<DefaultStreamMessageComposerState>().
Documentation, Migrations & Comments
CLAUDE.md, migrations/{redesign/message_composer,v10-migration}.md, packages/stream_chat_flutter/README.md, packages/stream_chat_flutter/lib/src/{localization/translations,message_input/{enums,message_input_placeholder,attachment_picker/stream_attachment_picker_controller},message_list_view/message_list_view,utils/typedefs}.dart, docs/docs_screenshots/test/src/mocks.dart
All documentation and inline comments updated: StreamMessageInput/StreamChatMessageComposerStreamMessageComposer/StreamChatMessageInput. Migration guides detail breaking changes: hideSendAsDmcanAlsoSendToChannelFromThread (inverted), attachmentLimit now optional, removed constructor parameters, placeholder resolution via placeholderBuilder, new attachmentPickerOptionsBuilder callback pattern. Localization comment for setupMockChannel updated.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 From MessageInput came the great composer refactor,
StreamMessageComposer now leads the design chapter,
While StreamChatMessageInput shines with voices recorded,
The old twin voices merged—a cleaner path, well-sorted!
Hops of joy through props and flows, examples all remade,
A redesign complete, the foundation strong and stayed. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(UI): rename message input' accurately and concisely describes the main change: renaming StreamMessageInput to StreamMessageComposer and StreamChatMessageComposer to StreamChatMessageInput across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/rename-message-input

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@renefloor renefloor changed the title feat(UI) : rename message input feat(UI): rename message input May 5, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart (1)

10-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the stale message parameter docs.

The constructor comment still documents [message], but MessageComposerComponentProps no longer exposes that field. That leaves the generated API docs pointing to a nonexistent argument.

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

In
`@packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart`
around lines 10 - 18, The constructor doc for MessageComposerComponentProps
still references a nonexistent [message] parameter; edit the doc comment above
the const MessageComposerComponentProps(...) to remove the stale `/// [message]
is the message for the message composer component.` line (or any other mention
of `message`) so the generated API docs no longer point to a non-existent
argument.
🧹 Nitpick comments (4)
packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_input.dart (1)

279-289: 💤 Low value

Inverted early-return is confusing in onLongPressCancel.

The check if (audioRecorderController.isRecording) return; plus the comment "Return if the recording is already started" implies the cancel path is only meaningful when recording has not started — which matches Flutter's onLongPressCancel semantics (fires before recognition). However, the parallel onLongPressStart uses the same exact guard with the same comment to prevent double-start. Consider tightening the comment to clarify that we want the "hold to record" hint to be shown only when the user released before recording began.

-        onLongPressCancel: () async {
-          // Return if the recording is already started.
-          if (audioRecorderController.isRecording) return;
+        onLongPressCancel: () async {
+          // Skip if recording has already started; cancel only handles
+          // the case where the long-press never reached recognition.
+          if (audioRecorderController.isRecording) return;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_input.dart`
around lines 279 - 289, Clarify the inverted early-return in onLongPressCancel:
the guard currently reads "Return if the recording is already started" but this
callback should show the "hold to record" hint only when recording has NOT
started. Update the comment on the check in onLongPressCancel (and make it
symmetric with onLongPressStart) to state that if
audioRecorderController.isRecording is true we should bail because a recording
is already in progress, otherwise call
widget.feedback.onRecordStartCancel(context) and
audioRecorderController.showInfo(context.translations.holdToRecordLabel) to
inform the user they released before recording began; reference
onLongPressCancel, audioRecorderController.isRecording,
widget.feedback.onRecordStartCancel, audioRecorderController.showInfo and
context.translations.holdToRecordLabel when locating the change.
packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart (1)

61-99: ⚖️ Poor tradeoff

Consider exposing a MessageComposerProps constructor alongside the named parameters.

The 35+ parameters are now duplicated three times across StreamMessageComposer, MessageComposerProps, and the parameter forwarding block. A StreamMessageComposer.fromProps({required MessageComposerProps props}) named constructor (or making the public ctor take a props object) would let advanced callers and component-factory authors reuse a MessageComposerProps instance without re-listing every field, while keeping the convenience constructor for typical usage.

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

In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart`
around lines 61 - 99, The constructor duplicates 30+ parameters between
StreamMessageComposer and MessageComposerProps; add a second constructor
StreamMessageComposer.fromProps({required MessageComposerProps props, Key? key})
(or change the public ctor to accept an optional props parameter) and wire that
constructor to set this.props directly so callers can pass a pre-built
MessageComposerProps instead of re-specifying every field; keep the existing
named-parameter convenience ctor but refactor it to build
MessageComposerProps(...) and forward to the new fromProps initializer to avoid
parameter duplication and ensure symbols StreamMessageComposer and
MessageComposerProps are used consistently.
packages/stream_chat_flutter/example/lib/tutorial_part_4.dart (1)

147-151: ⚡ Quick win

StreamMessageInputController created in build() is never disposed — resource leak.

StreamMessageInputController is a ValueNotifier that requires an explicit dispose() call. Creating it inline inside a StatelessWidget.build() means a new instance leaks on every rebuild with no disposal path. As tutorial code, this also models the pattern incorrectly for developers.

StreamMessageInputController requires messageInputController.dispose() to be called in the owning state's dispose() method.

Convert ThreadPage to a StatefulWidget to manage the controller lifecycle properly.

🛡️ Proposed fix
-class ThreadPage extends StatelessWidget {
-  const ThreadPage({
+class ThreadPage extends StatefulWidget {
+  const ThreadPage({
     super.key,
     this.parent,
   });
 
   final Message? parent;
 
   `@override`
-  Widget build(BuildContext context) {
+  State<ThreadPage> createState() => _ThreadPageState();
+}
+
+class _ThreadPageState extends State<ThreadPage> {
+  late final StreamMessageInputController _messageInputController =
+      StreamMessageInputController(message: Message(parentId: widget.parent!.id));
+
+  `@override`
+  void dispose() {
+    _messageInputController.dispose();
+    super.dispose();
+  }
+
+  `@override`
+  Widget build(BuildContext context) {
     return Scaffold(
       appBar: StreamThreadHeader(
-        parent: parent!,
+        parent: widget.parent!,
       ),
       body: Column(
         children: <Widget>[
           Expanded(
             child: StreamMessageListView(
-              parentMessage: parent,
+              parentMessage: widget.parent,
             ),
           ),
           StreamMessageComposer(
-            messageInputController: StreamMessageInputController(
-              message: Message(parentId: parent!.id),
-            ),
+            messageInputController: _messageInputController,
           ),
         ],
       ),
     );
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stream_chat_flutter/example/lib/tutorial_part_4.dart` around lines
147 - 151, ThreadPage currently constructs StreamMessageInputController inline
in build(), leaking a ValueNotifier on each rebuild; convert ThreadPage from a
StatelessWidget to a StatefulWidget, move instantiation of
StreamMessageInputController (with Message(parentId: parent!.id)) into the State
class (initState) and store it as a field, pass that field into
StreamMessageComposer via the messageInputController parameter, and override
dispose() in the State to call messageInputController.dispose() to properly
release resources.
packages/stream_chat_flutter/example/lib/tutorial_part_6.dart (1)

177-181: ⚡ Quick win

Same StreamMessageInputController disposal issue as tutorial_part_4.dart.

ThreadPage here is also a StatelessWidget creating a StreamMessageInputController inline in build(). Apply the same StatefulWidget refactor described for tutorial_part_4.dart.

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

In `@packages/stream_chat_flutter/example/lib/tutorial_part_6.dart` around lines
177 - 181, ThreadPage currently creates a StreamMessageInputController inline
inside build() (via StreamMessageInputController(message: Message(parentId:
parent!.id))) which leads to the same disposal/leak issue as in
tutorial_part_4.dart; refactor ThreadPage from a StatelessWidget to a
StatefulWidget, add a private StreamMessageInputController field (initialized in
initState using Message(parentId: parent!.id) or using widget props), pass that
controller into StreamMessageComposer, and override dispose() to call
controller.dispose() so the controller is created once per widget instance and
properly cleaned up.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@migrations/redesign/message_composer.md`:
- Line 87: The phrasing incorrectly states the removed parameters were in an
older StreamMessageComposer; update the sentence and any related headings to
state that the parameters previously belonged to StreamMessageInput (the
pre-migration type) and not StreamMessageComposer (the new name introduced by
this PR). Locate the sentence "Many parameters that existed in older versions of
`StreamMessageComposer` have been removed." and change it to reference
`StreamMessageInput`, and scan the surrounding paragraph/table captions to
ensure all mentions consistently say "StreamMessageInput" (or "previous
StreamMessageInput") as the source of the removed parameters.

In `@packages/stream_chat_flutter/lib/src/localization/translations.dart`:
- Around line 102-104: Fix the typo in the doc comment for the getter
alsoSendAsDirectMessageLabel by removing the stray extra double-quote so the
sentence reads correctly (e.g., change 'checkbox""' to 'checkbox'); update the
three-line comment above String get alsoSendAsDirectMessageLabel; to ensure
generated docs don't contain the unintended quote.

In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart`:
- Around line 1015-1031: The addedAttachments lookup is using
pickerController.value.attachments but addedIds are IDs present in
_effectiveController.attachments (message controller) and absent from the
picker, so firstWhere will throw; change the mapping that builds
addedAttachments to search _effectiveController.attachments (or the effective
controller's attachments collection used elsewhere in this file) instead of
pickerController.value.attachments so you retrieve the actual attachments to add
before calling pickerController.addAttachment for each.

In `@packages/stream_chat_flutter/README.md`:
- Line 102: Update the broken README link for StreamMessageComposer: replace the
non-existent URL ending with /stream_message_composer/ with the correct Stream
docs path following the message_composer pattern (e.g.,
/message_composer/stream_message_input/), so the README's StreamMessageComposer
link points to the valid documentation page for
StreamMessageComposer/StreamMessageInput.

---

Outside diff comments:
In
`@packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart`:
- Around line 10-18: The constructor doc for MessageComposerComponentProps still
references a nonexistent [message] parameter; edit the doc comment above the
const MessageComposerComponentProps(...) to remove the stale `/// [message] is
the message for the message composer component.` line (or any other mention of
`message`) so the generated API docs no longer point to a non-existent argument.

---

Nitpick comments:
In `@packages/stream_chat_flutter/example/lib/tutorial_part_4.dart`:
- Around line 147-151: ThreadPage currently constructs
StreamMessageInputController inline in build(), leaking a ValueNotifier on each
rebuild; convert ThreadPage from a StatelessWidget to a StatefulWidget, move
instantiation of StreamMessageInputController (with Message(parentId:
parent!.id)) into the State class (initState) and store it as a field, pass that
field into StreamMessageComposer via the messageInputController parameter, and
override dispose() in the State to call messageInputController.dispose() to
properly release resources.

In `@packages/stream_chat_flutter/example/lib/tutorial_part_6.dart`:
- Around line 177-181: ThreadPage currently creates a
StreamMessageInputController inline inside build() (via
StreamMessageInputController(message: Message(parentId: parent!.id))) which
leads to the same disposal/leak issue as in tutorial_part_4.dart; refactor
ThreadPage from a StatelessWidget to a StatefulWidget, add a private
StreamMessageInputController field (initialized in initState using
Message(parentId: parent!.id) or using widget props), pass that controller into
StreamMessageComposer, and override dispose() to call controller.dispose() so
the controller is created once per widget instance and properly cleaned up.

In
`@packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_input.dart`:
- Around line 279-289: Clarify the inverted early-return in onLongPressCancel:
the guard currently reads "Return if the recording is already started" but this
callback should show the "hold to record" hint only when recording has NOT
started. Update the comment on the check in onLongPressCancel (and make it
symmetric with onLongPressStart) to state that if
audioRecorderController.isRecording is true we should bail because a recording
is already in progress, otherwise call
widget.feedback.onRecordStartCancel(context) and
audioRecorderController.showInfo(context.translations.holdToRecordLabel) to
inform the user they released before recording began; reference
onLongPressCancel, audioRecorderController.isRecording,
widget.feedback.onRecordStartCancel, audioRecorderController.showInfo and
context.translations.holdToRecordLabel when locating the change.

In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart`:
- Around line 61-99: The constructor duplicates 30+ parameters between
StreamMessageComposer and MessageComposerProps; add a second constructor
StreamMessageComposer.fromProps({required MessageComposerProps props, Key? key})
(or change the public ctor to accept an optional props parameter) and wire that
constructor to set this.props directly so callers can pass a pre-built
MessageComposerProps instead of re-specifying every field; keep the existing
named-parameter convenience ctor but refactor it to build
MessageComposerProps(...) and forward to the new fromProps initializer to avoid
parameter duplication and ensure symbols StreamMessageComposer and
MessageComposerProps are used consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5e14197-b508-429e-9ffb-356922ce3374

📥 Commits

Reviewing files that changed from the base of the PR and between c2cdf29 and c1e640c.

📒 Files selected for processing (36)
  • CLAUDE.md
  • docs/docs_screenshots/test/message_input/stream_message_composer_test.dart
  • docs/docs_screenshots/test/src/mocks.dart
  • docs/docs_screenshots/test/voice_recording/voice_recording_test.dart
  • migrations/redesign/message_composer.md
  • migrations/v10-migration.md
  • packages/stream_chat_flutter/README.md
  • packages/stream_chat_flutter/example/lib/main.dart
  • packages/stream_chat_flutter/example/lib/split_view.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_1.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_2.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_3.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_4.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_5.dart
  • packages/stream_chat_flutter/example/lib/tutorial_part_6.dart
  • packages/stream_chat_flutter/lib/src/components/message_composer/message_composer.dart
  • packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart
  • packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input.dart
  • packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_composer.dart
  • packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_input.dart
  • packages/stream_chat_flutter/lib/src/keyboard_shortcuts/keysets.dart
  • packages/stream_chat_flutter/lib/src/localization/translations.dart
  • packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_controller.dart
  • packages/stream_chat_flutter/lib/src/message_input/enums.dart
  • packages/stream_chat_flutter/lib/src/message_input/message_input_placeholder.dart
  • packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart
  • packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart
  • packages/stream_chat_flutter/lib/src/utils/typedefs.dart
  • packages/stream_chat_flutter/lib/stream_chat_flutter.dart
  • packages/stream_chat_flutter/test/src/message_input/message_input_test.dart
  • packages/stream_chat_localizations/example/lib/add_new_lang.dart
  • packages/stream_chat_localizations/example/lib/main.dart
  • packages/stream_chat_localizations/example/lib/override_lang.dart
  • sample_app/lib/pages/channel_page.dart
  • sample_app/lib/pages/new_chat_screen.dart
  • sample_app/lib/pages/thread_page.dart
💤 Files with no reviewable changes (1)
  • packages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_composer.dart

Comment thread migrations/redesign/message_composer.md Outdated
### Removed parameters

Many parameters that existed in older versions of `StreamMessageInput` have been removed. The table below lists each removed parameter and the recommended migration path.
Many parameters that existed in older versions of `StreamMessageComposer` have been removed. The table below lists each removed parameter and the recommended migration path.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Misleading phrasing: parameters were in StreamMessageInput, not older StreamMessageComposer

The current wording implies the removed parameters once existed in a prior release of StreamMessageComposer, but StreamMessageComposer is the new name introduced by this very PR. A v9 or stable-SDK developer migrating here never used StreamMessageComposer; the parameters lived in StreamMessageInput.

📝 Suggested fix
-Many parameters that existed in older versions of `StreamMessageComposer` have been removed. The table below lists each removed parameter and the recommended migration path.
+Many parameters that existed in `StreamMessageInput` have been removed from `StreamMessageComposer`. The table below lists each removed parameter and the recommended migration path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@migrations/redesign/message_composer.md` at line 87, The phrasing incorrectly
states the removed parameters were in an older StreamMessageComposer; update the
sentence and any related headings to state that the parameters previously
belonged to StreamMessageInput (the pre-migration type) and not
StreamMessageComposer (the new name introduced by this PR). Locate the sentence
"Many parameters that existed in older versions of `StreamMessageComposer` have
been removed." and change it to reference `StreamMessageInput`, and scan the
surrounding paragraph/table captions to ensure all mentions consistently say
"StreamMessageInput" (or "previous StreamMessageInput") as the source of the
removed parameters.

Comment on lines 102 to 104
/// The label for also send
/// as direct message "checkbox"" in [StreamMessageInput]
/// as direct message "checkbox"" in [StreamMessageComposer]
String get alsoSendAsDirectMessageLabel;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix doc typo in translation API comment.

Line 103 has an extra quote in checkbox"", which will leak into generated docs.

✏️ Suggested fix
-  /// as direct message "checkbox"" in [StreamMessageComposer]
+  /// as direct message "checkbox" in [StreamMessageComposer]
📝 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
/// The label for also send
/// as direct message "checkbox"" in [StreamMessageInput]
/// as direct message "checkbox"" in [StreamMessageComposer]
String get alsoSendAsDirectMessageLabel;
/// The label for also send
/// as direct message "checkbox" in [StreamMessageComposer]
String get alsoSendAsDirectMessageLabel;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stream_chat_flutter/lib/src/localization/translations.dart` around
lines 102 - 104, Fix the typo in the doc comment for the getter
alsoSendAsDirectMessageLabel by removing the stray extra double-quote so the
sentence reads correctly (e.g., change 'checkbox""' to 'checkbox'); update the
three-line comment above String get alsoSendAsDirectMessageLabel; to ensure
generated docs don't contain the unintended quote.

Comment on lines 1015 to +1031
final removedIds = pickerIds.difference(messageIds);
if (removedIds.isEmpty) return;
final addedIds = messageIds.difference(pickerIds);

if (removedIds.isEmpty && addedIds.isEmpty) return;

final addedAttachments = addedIds
.map((id) => pickerController.value.attachments.firstWhere((a) => a.id == id))
.toList();

_isSyncingControllers = true;
try {
for (final id in removedIds) {
pickerController.removeAttachmentById(id);
}
for (final attachment in addedAttachments) {
pickerController.addAttachment(attachment);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical bug: addedAttachments looks up IDs in the wrong collection.

addedIds = messageIds.difference(pickerIds) are exactly the attachment IDs that exist in _effectiveController.attachments but not in pickerController.value.attachments. The subsequent firstWhere then searches the picker controller's attachments for those IDs and will throw a StateError for every added attachment because they are guaranteed to not be there.

The lookup must be done against the effective/message controller's attachments.

🐛 Proposed fix
     final removedIds = pickerIds.difference(messageIds);
     final addedIds = messageIds.difference(pickerIds);

     if (removedIds.isEmpty && addedIds.isEmpty) return;

     final addedAttachments = addedIds
-        .map((id) => pickerController.value.attachments.firstWhere((a) => a.id == id))
+        .map((id) => _effectiveController.attachments.firstWhere((a) => a.id == id))
         .toList();
📝 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
final removedIds = pickerIds.difference(messageIds);
if (removedIds.isEmpty) return;
final addedIds = messageIds.difference(pickerIds);
if (removedIds.isEmpty && addedIds.isEmpty) return;
final addedAttachments = addedIds
.map((id) => pickerController.value.attachments.firstWhere((a) => a.id == id))
.toList();
_isSyncingControllers = true;
try {
for (final id in removedIds) {
pickerController.removeAttachmentById(id);
}
for (final attachment in addedAttachments) {
pickerController.addAttachment(attachment);
}
final removedIds = pickerIds.difference(messageIds);
final addedIds = messageIds.difference(pickerIds);
if (removedIds.isEmpty && addedIds.isEmpty) return;
final addedAttachments = addedIds
.map((id) => _effectiveController.attachments.firstWhere((a) => a.id == id))
.toList();
_isSyncingControllers = true;
try {
for (final id in removedIds) {
pickerController.removeAttachmentById(id);
}
for (final attachment in addedAttachments) {
pickerController.addAttachment(attachment);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart`
around lines 1015 - 1031, The addedAttachments lookup is using
pickerController.value.attachments but addedIds are IDs present in
_effectiveController.attachments (message controller) and absent from the
picker, so firstWhere will throw; change the mapping that builds
addedAttachments to search _effectiveController.attachments (or the effective
controller's attachments collection used elsewhere in this file) instead of
pickerController.value.attachments so you retrieve the actual attachments to add
before calling pickerController.addAttachment for each.

- [StreamChannelHeader](https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_channel_header/)
- [StreamChannelListView](https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_channel_list_view/)
- [StreamMessageInput](https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_message_input/)
- [StreamMessageComposer](https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_message_composer/)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_message_composer/ - does this page exist?

💡 Result:

No—the specific URL you provided does not appear to exist (or at least is not present in Stream’s current Flutter docs structure). The closest existing Flutter doc is for StreamMessageInput at https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/message_composer/stream_message_input/ [1], which indicates that the message composer documentation lives under /message_composer/ but uses stream_message_input/ rather than stream_message_composer/ in the path [1]. Your URL: https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_message_composer/ was not found in the indexed results from Stream’s docs, while the existing related composer page under /message_composer/ was found [1].

Citations:


Fix the broken documentation link for StreamMessageComposer.

The URL https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/stream_message_composer/ does not exist. Stream's composer documentation follows the pattern /message_composer/stream_message_input/ (e.g., https://getstream.io/chat/docs/sdk/flutter/stream_chat_flutter/message_composer/stream_message_input/). Verify the correct path for StreamMessageComposer docs and update the link accordingly.

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

In `@packages/stream_chat_flutter/README.md` at line 102, Update the broken README
link for StreamMessageComposer: replace the non-existent URL ending with
/stream_message_composer/ with the correct Stream docs path following the
message_composer pattern (e.g., /message_composer/stream_message_input/), so the
README's StreamMessageComposer link points to the valid documentation page for
StreamMessageComposer/StreamMessageInput.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 57.89474% with 96 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.43%. Comparing base (c2cdf29) to head (13e1d0c).

Files with missing lines Patch % Lines
...ts/message_composer/stream_chat_message_input.dart 51.85% 52 Missing ⚠️
...lib/src/message_input/stream_message_composer.dart 50.70% 35 Missing ⚠️
...nents/message_composer/message_composer_input.dart 76.31% 9 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           v10.0.0    #2642      +/-   ##
===========================================
+ Coverage    67.13%   67.43%   +0.29%     
===========================================
  Files          418      419       +1     
  Lines        25200    25217      +17     
===========================================
+ Hits         16919    17004      +85     
+ Misses        8281     8213      -68     

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

@renefloor renefloor force-pushed the feature/rename-message-input branch from 5ed8948 to 976871d Compare May 5, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant