From 51a766b9880382ff9e4dc7c572cb7385948bd370 Mon Sep 17 00:00:00 2001 From: Rene Floor Date: Wed, 13 May 2026 16:34:12 +0200 Subject: [PATCH] rename input controller to composer controller --- .../stream_message_composer_test.dart | 8 +- .../voice_recording/voice_recording_test.dart | 8 +- migrations/redesign/message_composer.md | 4 +- packages/stream_chat_flutter/CHANGELOG.md | 1 + .../stream_chat_flutter/example/lib/main.dart | 12 +-- .../example/lib/tutorial_part_4.dart | 2 +- .../example/lib/tutorial_part_6.dart | 2 +- .../src/autocomplete/stream_autocomplete.dart | 85 +++++++++---------- .../message_composer_component_props.dart | 2 +- .../message_composer_input_center.dart | 4 +- .../message_composer_input_header.dart | 2 +- .../message_composer_input_trailing.dart | 2 +- .../message_composer_recording_locked.dart | 20 ++--- .../message_input_placeholder.dart | 8 +- .../stream_chat_message_input.dart | 10 +-- .../stream_message_composer.dart | 39 ++++----- .../stream_message_text_field.dart | 12 +-- .../lib/src/utils/typedefs.dart | 4 +- .../src/message_input/message_input_test.dart | 56 ++++++------ .../stream_chat_flutter_core/CHANGELOG.md | 18 ++-- packages/stream_chat_flutter_core/README.md | 2 +- .../example/lib/main.dart | 14 +-- ...> stream_message_composer_controller.dart} | 46 +++++----- .../lib/stream_chat_flutter_core.dart | 2 +- ...eam_message_composer_controller_test.dart} | 30 +++---- sample_app/lib/pages/channel_page.dart | 10 +-- sample_app/lib/pages/thread_page.dart | 8 +- 27 files changed, 206 insertions(+), 205 deletions(-) rename packages/stream_chat_flutter_core/lib/src/{stream_message_input_controller.dart => stream_message_composer_controller.dart} (89%) rename packages/stream_chat_flutter_core/test/{stream_message_input_controller_test.dart => stream_message_composer_controller_test.dart} (95%) diff --git a/docs/docs_screenshots/test/message_input/stream_message_composer_test.dart b/docs/docs_screenshots/test/message_input/stream_message_composer_test.dart index ddc3e68afa..44aab77dec 100644 --- a/docs/docs_screenshots/test/message_input/stream_message_composer_test.dart +++ b/docs/docs_screenshots/test/message_input/stream_message_composer_test.dart @@ -103,7 +103,7 @@ void main() { channelState: channelState, ); - final controller = StreamMessageInputController(); + final controller = StreamMessageComposerController(); return MaterialApp( theme: docsScreenshotsTheme(), @@ -125,7 +125,7 @@ void main() { body: Column( children: [ const Expanded(child: SizedBox()), - StreamMessageComposer(messageInputController: controller), + StreamMessageComposer(messageComposerController: controller), ], ), ), @@ -208,7 +208,7 @@ void main() { channelState: channelState, ); - final controller = StreamMessageInputController() + final controller = StreamMessageComposerController() ..quotedMessage = Message( id: 'quoted-msg', text: 'This is the original message', @@ -218,7 +218,7 @@ void main() { return _buildMessageInputScaffold( client: client, channel: channel, - messageInput: StreamMessageComposer(messageInputController: controller), + messageInput: StreamMessageComposer(messageComposerController: controller), ); }, ); diff --git a/docs/docs_screenshots/test/voice_recording/voice_recording_test.dart b/docs/docs_screenshots/test/voice_recording/voice_recording_test.dart index a8d8043123..608f9031f3 100644 --- a/docs/docs_screenshots/test/voice_recording/voice_recording_test.dart +++ b/docs/docs_screenshots/test/voice_recording/voice_recording_test.dart @@ -26,7 +26,7 @@ StreamAudioRecorderController _makeRecorderController(AudioRecorderState initial Widget _buildVoiceRecordingMessageInputScaffold({ required MockClient client, required MockChannel channel, - StreamMessageInputController? messageInputController, + StreamMessageComposerController? messageComposerController, }) { return MaterialApp( theme: docsScreenshotsTheme(), @@ -44,7 +44,7 @@ Widget _buildVoiceRecordingMessageInputScaffold({ Expanded(child: Container()), StreamMessageComposer( enableVoiceRecording: true, - messageInputController: messageInputController, + messageComposerController: messageComposerController, ), ], ), @@ -302,7 +302,7 @@ void main() { final channelState = MockChannelState(); _setupChannel(client, clientState, channel, channelState); - final messageInputController = StreamMessageInputController() + final messageComposerController = StreamMessageComposerController() ..addAttachment( Attachment( type: 'voiceRecording', @@ -318,7 +318,7 @@ void main() { return _buildVoiceRecordingMessageInputScaffold( client: client, channel: channel, - messageInputController: messageInputController, + messageComposerController: messageComposerController, ); }, ); diff --git a/migrations/redesign/message_composer.md b/migrations/redesign/message_composer.md index a1072210ef..7ba2c55014 100644 --- a/migrations/redesign/message_composer.md +++ b/migrations/redesign/message_composer.md @@ -154,7 +154,7 @@ Use this when you want the new design system visuals with custom business logic. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `onSendPressed` | `VoidCallback` | **required** | Called when the send button is pressed | -| `controller` | `StreamMessageInputController?` | `null` | Controller for the input; created internally if not provided | +| `controller` | `StreamMessageComposerController?` | `null` | Controller for the input; created internally if not provided | | `onAttachmentButtonPressed` | `VoidCallback?` | `null` | Called when the attachment button is pressed. When `null`, the attachment button is hidden. | | `isPickerOpen` | `bool` | `false` | Whether the inline attachment picker is currently open | | `focusNode` | `FocusNode?` | `null` | Focus node for the text field | @@ -259,7 +259,7 @@ Each case carries the contextual data relevant to that input state. Pattern-matc | Case | Field | Type | Description | |------|-------|------|-------------| | `WriteMessagePlaceholder` | `isEditing` | `bool` | `true` when the input is editing an existing message instead of composing a new one. Useful for swapping the placeholder while editing. | -| `SlowModePlaceholder` | `cooldownTimeOut` | `int` | Remaining slow-mode cooldown in seconds. Mirrors `StreamMessageInputController.cooldownTimeOut`. | +| `SlowModePlaceholder` | `cooldownTimeOut` | `int` | Remaining slow-mode cooldown in seconds. Mirrors `StreamMessageComposerController.cooldownTimeOut`. | | `SlowModePlaceholder` | `cooldown` | `Duration` | Convenience getter wrapping `cooldownTimeOut` for formatting timer strings. | | `CommandPlaceholder` | `command` | `String` | Active command name (e.g. `'giphy'`, `'mute'`, `'ban'`, or any backend-defined command). | | `AttachmentsPlaceholder` | `attachments` | `List` | Pending attachments held by the input. OG link previews are still included — filter via `Attachment.ogScrapeUrl` if you only want user-added ones. | diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index ef4f9bc63a..f94162b53a 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -6,6 +6,7 @@ 🛑️ Breaking +- Renamed `StreamMessageComposer.messageInputController` parameter to `messageComposerController`. - Removed `StreamDraftListView`, `StreamDraftListTile`, `StreamDraftListTileTheme`, and `StreamDraftListTileThemeData` from the SDK. Also removed `StreamChatThemeData.draftListTileTheme`. Refer to the sample app for a reference implementation using `StreamDraftListController` and `PagedValueListView`. - Renamed `StreamMessageComposerInput` → `StreamMessageComposerInputCenter` (and `DefaultStreamMessageComposerInput` → `DefaultStreamMessageComposerInputCenter`). The name `StreamMessageComposerInput` is now the input container widget (assembles header, leading, center, trailing). - Renamed `MessageComposerInputProps` → `MessageComposerInputCenterProps`. The name `MessageComposerInputProps` now refers to the new container widget's props. diff --git a/packages/stream_chat_flutter/example/lib/main.dart b/packages/stream_chat_flutter/example/lib/main.dart index d9d01f7b77..8bc7908ed5 100644 --- a/packages/stream_chat_flutter/example/lib/main.dart +++ b/packages/stream_chat_flutter/example/lib/main.dart @@ -220,7 +220,7 @@ class ChannelPage extends StatefulWidget { } class _ChannelPageState extends State { - late final messageInputController = StreamMessageInputController(); + late final messageComposerController = StreamMessageComposerController(); final focusNode = FocusNode(); @override @@ -270,9 +270,9 @@ class _ChannelPageState extends State { ), StreamMessageComposer( enableVoiceRecording: true, - onQuotedMessageCleared: messageInputController.clearQuotedMessage, + onQuotedMessageCleared: messageComposerController.clearQuotedMessage, focusNode: focusNode, - messageInputController: messageInputController, + messageComposerController: messageComposerController, ), ], ), @@ -280,7 +280,7 @@ class _ChannelPageState extends State { } void reply(Message message) { - messageInputController.quotedMessage = message; + messageComposerController.quotedMessage = message; WidgetsBinding.instance.addPostFrameCallback((timeStamp) { focusNode.requestFocus(); }); @@ -289,7 +289,7 @@ class _ChannelPageState extends State { @override void dispose() { focusNode.dispose(); - messageInputController.dispose(); + messageComposerController.dispose(); super.dispose(); } } @@ -317,7 +317,7 @@ class ThreadPage extends StatelessWidget { ), StreamMessageComposer( enableVoiceRecording: true, - messageInputController: StreamMessageInputController( + messageComposerController: StreamMessageComposerController( message: Message(parentId: parent.id), ), ), diff --git a/packages/stream_chat_flutter/example/lib/tutorial_part_4.dart b/packages/stream_chat_flutter/example/lib/tutorial_part_4.dart index 1afeaf6da8..dcf77b4098 100644 --- a/packages/stream_chat_flutter/example/lib/tutorial_part_4.dart +++ b/packages/stream_chat_flutter/example/lib/tutorial_part_4.dart @@ -145,7 +145,7 @@ class ThreadPage extends StatelessWidget { ), ), StreamMessageComposer( - messageInputController: StreamMessageInputController( + messageComposerController: StreamMessageComposerController( message: Message(parentId: parent!.id), ), ), diff --git a/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart b/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart index d574652349..bdb73b53f9 100644 --- a/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart +++ b/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart @@ -175,7 +175,7 @@ class ThreadPage extends StatelessWidget { ), ), StreamMessageComposer( - messageInputController: StreamMessageInputController( + messageComposerController: StreamMessageComposerController( message: Message(parentId: parent!.id), ), ), diff --git a/packages/stream_chat_flutter/lib/src/autocomplete/stream_autocomplete.dart b/packages/stream_chat_flutter/lib/src/autocomplete/stream_autocomplete.dart index c452b10e9c..b57029ab83 100644 --- a/packages/stream_chat_flutter/lib/src/autocomplete/stream_autocomplete.dart +++ b/packages/stream_chat_flutter/lib/src/autocomplete/stream_autocomplete.dart @@ -7,9 +7,6 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; export 'stream_command_autocomplete_options.dart'; export 'stream_mention_autocomplete_options.dart'; -/// {@macro stream_chat_flutter.StreamMessageInputController} -typedef StreamMessageEditingController = StreamMessageInputController; - /// Positions the [AutocompleteTrigger] options around the [TextField] or /// [TextFormField] that triggered the autocomplete. enum OptionsAlignment { @@ -49,7 +46,7 @@ enum OptionsAlignment { typedef StreamAutocompleteFieldViewBuilder = Widget Function( BuildContext context, - StreamMessageEditingController messageEditingController, + StreamMessageComposerController messageComposerController, FocusNode focusNode, ); @@ -63,7 +60,7 @@ typedef StreamAutocompleteOptionsViewBuilder = Widget Function( BuildContext context, StreamAutocompleteQuery autocompleteQuery, - StreamMessageEditingController messageEditingController, + StreamMessageComposerController messageComposerController, ); /// The query to determine the autocomplete options. @@ -204,19 +201,19 @@ class StreamAutocomplete extends StatefulWidget { const StreamAutocomplete({ super.key, this.focusNode, - this.messageEditingController, + this.messageComposerController, required this.autocompleteTriggers, this.fieldViewBuilder = _defaultFieldViewBuilder, this.optionsAlignment = OptionsAlignment.above, this.debounceDuration = const Duration(milliseconds: 300), - }) : assert((focusNode == null) == (messageEditingController == null), ''); + }) : assert((focusNode == null) == (messageComposerController == null), ''); /// The triggers that trigger autocomplete. final Iterable autocompleteTriggers; /// Builds the field whose input is used to get the options. /// - /// Pass the provided [StreamMessageEditingController] to the field built + /// Pass the provided [StreamMessageComposerController] to the field built /// here so that StreamAutocomplete can listen for changes. final StreamAutocompleteFieldViewBuilder fieldViewBuilder; @@ -230,17 +227,17 @@ class StreamAutocomplete extends StatefulWidget { /// When following this pattern, [fieldViewBuilder] can return /// `EmptyWidget()` so that nothing is drawn where the text field would /// normally be. A separate text field can be created elsewhere, and a - /// FocusNode and StreamMessageEditingController can be passed both to that + /// FocusNode and StreamMessageComposerController can be passed both to that /// text field and to StreamAutocomplete. /// - /// If this parameter is not null, then [messageEditingController] must also + /// If this parameter is not null, then [messageComposerController] must also /// be not null. final FocusNode? focusNode; - /// The [StreamMessageEditingController] that is used for the text field. + /// The [StreamMessageComposerController] that is used for the text field. /// /// If this parameter is not null, then [focusNode] must also be not null. - final StreamMessageEditingController? messageEditingController; + final StreamMessageComposerController? messageComposerController; /// The alignment of the options. /// @@ -248,19 +245,19 @@ class StreamAutocomplete extends StatefulWidget { final OptionsAlignment optionsAlignment; /// The duration of the debounce period for the - /// [StreamMessageEditingController]. + /// [StreamMessageComposerController]. /// /// The default value is [300ms]. final Duration debounceDuration; static Widget _defaultFieldViewBuilder( BuildContext context, - StreamMessageEditingController messageEditingController, + StreamMessageComposerController messageComposerController, FocusNode focusNode, ) { return _StreamAutocompleteField( focusNode: focusNode, - messageEditingController: messageEditingController, + messageComposerController: messageComposerController, ); } @@ -276,7 +273,7 @@ class StreamAutocomplete extends StatefulWidget { } class _StreamAutocompleteState extends State { - late StreamMessageEditingController _messageEditingController; + late StreamMessageComposerController _messageComposerController; late FocusNode _focusNode; StreamAutocompleteQuery? _currentQuery; @@ -305,7 +302,7 @@ class _StreamAutocompleteState extends State { if (query == null || trigger == null) return; final querySelection = query.selection; - final text = _messageEditingController.text; + final text = _messageComposerController.text; var start = querySelection.baseOffset; if (!keepTrigger) start -= 1; @@ -325,7 +322,7 @@ class _StreamAutocompleteState extends State { final newText = text.replaceRange(start, end, option); final newSelection = TextSelection.collapsed(offset: selectionOffset); - _messageEditingController.textEditingValue = TextEditingValue( + _messageComposerController.textEditingValue = TextEditingValue( text: newText, selection: newSelection, ); @@ -372,11 +369,11 @@ class _StreamAutocompleteState extends State { return null; } - // Called when _textEditingController changes. + // Called when _messageComposerController changes. late final _onChangedField = debounce( () { - final messageValue = _messageEditingController.message; - final textEditingValue = _messageEditingController.textEditingValue; + final messageValue = _messageComposerController.message; + final textEditingValue = _messageComposerController.textEditingValue; // If the content has not changed, then there is nothing to do. if (textEditingValue.text == _lastFieldText) return; @@ -416,28 +413,28 @@ class _StreamAutocompleteState extends State { if (mounted) setState(() {}); } - // Handle a potential change in textEditingController by properly disposing of - // the old one and setting up the new one, if needed. + // Handle a potential change in messageComposerController by properly + // disposing of the old one and setting up the new one, if needed. void _updateTextEditingController( - StreamMessageEditingController? old, - StreamMessageEditingController? current, + StreamMessageComposerController? old, + StreamMessageComposerController? current, ) { if ((old == null && current == null) || old == current) { return; } if (old == null) { - _messageEditingController + _messageComposerController ..removeListener(_onChangedField) ..dispose(); - _messageEditingController = current!; + _messageComposerController = current!; } else if (current == null) { - _messageEditingController.removeListener(_onChangedField); - _messageEditingController = StreamMessageEditingController(); + _messageComposerController.removeListener(_onChangedField); + _messageComposerController = StreamMessageComposerController(); } else { - _messageEditingController.removeListener(_onChangedField); - _messageEditingController = current; + _messageComposerController.removeListener(_onChangedField); + _messageComposerController = current; } - _messageEditingController.addListener(_onChangedField); + _messageComposerController.addListener(_onChangedField); } // Handle a potential change in focusNode by properly disposing of the old one @@ -464,8 +461,8 @@ class _StreamAutocompleteState extends State { @override void initState() { super.initState(); - _messageEditingController = widget.messageEditingController ?? StreamMessageEditingController(); - _messageEditingController.addListener(_onChangedField); + _messageComposerController = widget.messageComposerController ?? StreamMessageComposerController(); + _messageComposerController.addListener(_onChangedField); _focusNode = widget.focusNode ?? FocusNode(); _focusNode.addListener(_onChangedFocus); } @@ -474,17 +471,17 @@ class _StreamAutocompleteState extends State { void didUpdateWidget(StreamAutocomplete oldWidget) { super.didUpdateWidget(oldWidget); _updateTextEditingController( - oldWidget.messageEditingController, - widget.messageEditingController, + oldWidget.messageComposerController, + widget.messageComposerController, ); _updateFocusNode(oldWidget.focusNode, widget.focusNode); } @override void dispose() { - _messageEditingController.removeListener(_onChangedField); - if (widget.messageEditingController == null) { - _messageEditingController.dispose(); + _messageComposerController.removeListener(_onChangedField); + if (widget.messageComposerController == null) { + _messageComposerController.dispose(); } _focusNode.removeListener(_onChangedFocus); if (widget.focusNode == null) { @@ -508,7 +505,7 @@ class _StreamAutocompleteState extends State { child: _currentTrigger!.optionsViewBuilder( context, _currentQuery!, - _messageEditingController, + _messageComposerController, ), ) : null; @@ -519,7 +516,7 @@ class _StreamAutocompleteState extends State { portalFollower: optionViewBuilder, child: widget.fieldViewBuilder( context, - _messageEditingController, + _messageComposerController, _focusNode, ), ); @@ -532,17 +529,17 @@ class _StreamAutocompleteState extends State { class _StreamAutocompleteField extends StatelessWidget { const _StreamAutocompleteField({ required this.focusNode, - required this.messageEditingController, + required this.messageComposerController, }); final FocusNode focusNode; - final StreamMessageEditingController messageEditingController; + final StreamMessageComposerController messageComposerController; @override Widget build(BuildContext context) { return StreamMessageTextField( - controller: messageEditingController, + controller: messageComposerController, focusNode: focusNode, ); } diff --git a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart index 1a0dcb7aa4..c9acbb2a61 100644 --- a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart +++ b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dart @@ -51,7 +51,7 @@ class MessageComposerComponentProps { }); /// The controller for the message composer component. - final StreamMessageInputController controller; + final StreamMessageComposerController controller; /// Whether the message composer is floating. final bool isFloating; diff --git a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_center.dart b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_center.dart index 1bbc01e61f..53a02c3955 100644 --- a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_center.dart +++ b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_center.dart @@ -47,14 +47,14 @@ class DefaultStreamMessageComposerInputCenter extends StatelessWidget { RecordStateRecordingLocked() => MessageComposerRecordingLocked( audioRecorderController: recorder, feedback: props.feedback, - messageInputController: props.controller, + messageComposerController: props.controller, sendMessageCallback: sendMessageCallback, state: audioState, ), RecordStateStopped() => MessageComposerRecordingStopped( audioRecorderController: recorder, feedback: props.feedback, - messageInputController: props.controller, + messageComposerController: props.controller, sendMessageCallback: sendMessageCallback, recordingState: audioState, ), diff --git a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart index 845dbb58e4..2bfb0489e7 100644 --- a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart +++ b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart @@ -26,7 +26,7 @@ class _DefaultStreamMessageComposerInputHeader extends StatelessWidget { const _DefaultStreamMessageComposerInputHeader({required this.props}); final MessageComposerComponentProps props; - StreamMessageInputController get controller => props.controller; + StreamMessageComposerController get controller => props.controller; @override Widget build(BuildContext context) { diff --git a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_trailing.dart b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_trailing.dart index 8d6a25b528..0681245311 100644 --- a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_trailing.dart +++ b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_trailing.dart @@ -34,7 +34,7 @@ class DefaultStreamMessageComposerInputTrailing extends StatelessWidget { /// The properties for the message composer component. final MessageComposerComponentProps props; - StreamMessageInputController get _controller => props.controller; + StreamMessageComposerController get _controller => props.controller; @override Widget build(BuildContext context) { diff --git a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_recording_locked.dart b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_recording_locked.dart index 1d56faf422..4448947824 100644 --- a/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_recording_locked.dart +++ b/packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_recording_locked.dart @@ -14,13 +14,13 @@ class MessageComposerRecordingLocked extends StatelessWidget { /// Creates a new instance of [MessageComposerRecordingLocked]. /// [audioRecorderController] is the controller for the audio recorder. /// [feedback] is the feedback for the audio recorder. - /// [messageInputController] is the controller for the message input. + /// [messageComposerController] is the controller for the message composer. /// [sendMessageCallback] is the callback for when the message is sent automatically. const MessageComposerRecordingLocked({ super.key, required this.audioRecorderController, required this.feedback, - required this.messageInputController, + required this.messageComposerController, required this.sendMessageCallback, required this.state, }); @@ -31,8 +31,8 @@ class MessageComposerRecordingLocked extends StatelessWidget { /// The feedback for the audio recorder. final AudioRecorderFeedback feedback; - /// The controller for the message input. - final StreamMessageInputController messageInputController; + /// The controller for the message composer. + final StreamMessageComposerController messageComposerController; /// The callback for when the message is sent automatically. /// This callback should be null when the message is not supposed to be sent automatically. @@ -110,7 +110,7 @@ class MessageComposerRecordingLocked extends StatelessWidget { await feedback.onRecordFinish(context); final audio = await audioRecorderController.finishRecord(); if (audio != null) { - messageInputController.addAttachment(audio); + messageComposerController.addAttachment(audio); } // Once the recording is finished, cancel the recorder. @@ -134,13 +134,13 @@ class MessageComposerRecordingStopped extends StatefulWidget { /// Creates a new instance of [MessageComposerRecordingStopped]. /// [audioRecorderController] is the controller for the audio recorder. /// [feedback] is the feedback for the audio recorder. - /// [messageInputController] is the controller for the message input. + /// [messageComposerController] is the controller for the message composer. /// [sendMessageCallback] is the callback for when the message is sent automatically. const MessageComposerRecordingStopped({ super.key, required this.audioRecorderController, required this.feedback, - required this.messageInputController, + required this.messageComposerController, required this.sendMessageCallback, required this.recordingState, }); @@ -151,8 +151,8 @@ class MessageComposerRecordingStopped extends StatefulWidget { /// The feedback for the audio recorder. final AudioRecorderFeedback feedback; - /// The controller for the message input. - final StreamMessageInputController messageInputController; + /// The controller for the message composer. + final StreamMessageComposerController messageComposerController; /// The callback for when the message is sent automatically. /// This callback should be null when the message is not supposed to be sent automatically. @@ -307,7 +307,7 @@ class _MessageComposerRecordingStoppedState extends State { - late StreamMessageInputController _controller; + late StreamMessageComposerController _controller; @override void initState() { @@ -127,7 +127,7 @@ class _StreamChatMessageInputState extends State { } void _initController() { - _controller = widget.controller ?? StreamMessageInputController(); + _controller = widget.controller ?? StreamMessageComposerController(); } @override @@ -194,7 +194,7 @@ class _StreamChatMessageInputContent extends StatelessWidget { }); final StreamChatMessageInput widget; - final StreamMessageInputController inputController; + final StreamMessageComposerController inputController; final AudioRecorderState audioRecorderState; static const double _lockRecordThreshold = 50; diff --git a/packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart b/packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart index 58c5df0ad7..b28aa7c3a4 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/stream_message_composer.dart @@ -64,7 +64,7 @@ class StreamMessageComposer extends StatelessWidget { super.key, void Function(Message)? onMessageSent, FutureOr Function(Message)? preMessageSending, - StreamMessageInputController? messageInputController, + StreamMessageComposerController? messageComposerController, FocusNode? focusNode, bool disableAttachments = false, int maxAttachmentSize = kDefaultMaxAttachmentSize, @@ -101,7 +101,7 @@ class StreamMessageComposer extends StatelessWidget { }) : props = MessageComposerProps( onMessageSent: onMessageSent, preMessageSending: preMessageSending, - messageInputController: messageInputController, + messageComposerController: messageComposerController, focusNode: focusNode, disableAttachments: disableAttachments, maxAttachmentSize: maxAttachmentSize, @@ -162,7 +162,7 @@ class MessageComposerProps { const MessageComposerProps({ this.onMessageSent, this.preMessageSending, - this.messageInputController, + this.messageComposerController, this.focusNode, this.disableAttachments = false, this.maxAttachmentSize = kDefaultMaxAttachmentSize, @@ -206,8 +206,8 @@ class MessageComposerProps { /// Use this to transform the message. final FutureOr Function(Message)? preMessageSending; - /// The text controller of the TextField. - final StreamMessageInputController? messageInputController; + /// The controller for the message composer. + final StreamMessageComposerController? messageComposerController; /// The focus node associated to the TextField. final FocusNode? focusNode; @@ -323,7 +323,7 @@ class MessageComposerProps { /// Resolves the placeholder text shown inside the input field. /// /// Receives the current [MessageInputPlaceholder] state (resolved from the - /// active [StreamMessageInputController]) and returns the string to display. + /// active [StreamMessageComposerController]) and returns the string to display. /// Override this callback to provide custom placeholders for /// backend-defined commands or any other input state — pattern-match /// exhaustively over the sealed [MessageInputPlaceholder] cases: @@ -486,18 +486,19 @@ class DefaultStreamMessageComposerState extends State widget.props.focusNode ?? (_focusNode ??= FocusNode()); FocusNode? _focusNode; - StreamMessageInputController get _effectiveController => widget.props.messageInputController ?? _controller!.value; - StreamRestorableMessageInputController? _controller; + StreamMessageComposerController get _effectiveController => + widget.props.messageComposerController ?? _controller!.value; + StreamRestorableMessageComposerController? _controller; void _createLocalController([Message? message]) { assert(_controller == null, ''); - _controller = StreamRestorableMessageInputController(message: message); + _controller = StreamRestorableMessageComposerController(message: message); } void _registerController() { assert(_controller != null, ''); - registerForRestoration(_controller!, 'messageInputController'); + registerForRestoration(_controller!, 'messageComposerController'); _initialiseEffectiveController(); } @@ -524,7 +525,7 @@ class DefaultStreamMessageComposerState extends State attachments) { if (widget.props.attachmentLimit case final limit?) { final length = _effectiveController.attachments.length + attachments.length; diff --git a/packages/stream_chat_flutter/lib/src/message_input/stream_message_text_field.dart b/packages/stream_chat_flutter/lib/src/message_input/stream_message_text_field.dart index b6e9391a79..72bc824496 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/stream_message_text_field.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/stream_message_text_field.dart @@ -147,8 +147,8 @@ class StreamMessageTextField extends StatefulWidget { /// Controls the message being edited. /// - /// If null, this widget will create its own [StreamMessageInputController]. - final StreamMessageInputController? controller; + /// If null, this widget will create its own [StreamMessageComposerController]. + final StreamMessageComposerController? controller; /// Defines the keyboard focus for this widget. /// @@ -511,7 +511,7 @@ class StreamMessageTextField extends StatefulWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('controller', controller, defaultValue: null)) + ..add(DiagnosticsProperty('controller', controller, defaultValue: null)) ..add(DiagnosticsProperty('focusNode', focusNode, defaultValue: null)) ..add(DiagnosticsProperty('enabled', enabled, defaultValue: null)) ..add(DiagnosticsProperty('decoration', decoration, defaultValue: const InputDecoration())) @@ -582,8 +582,8 @@ class StreamMessageTextField extends StatefulWidget { } class _StreamMessageTextFieldState extends State with RestorationMixin { - StreamMessageInputController get _effectiveController => widget.controller ?? _controller!.value; - StreamRestorableMessageInputController? _controller; + StreamMessageComposerController get _effectiveController => widget.controller ?? _controller!.value; + StreamRestorableMessageComposerController? _controller; @override void initState() { @@ -595,7 +595,7 @@ class _StreamMessageTextFieldState extends State with Re void _createLocalController([Message? message]) { assert(_controller == null, ''); - _controller = StreamRestorableMessageInputController(message: message); + _controller = StreamRestorableMessageComposerController(message: message); } @override diff --git a/packages/stream_chat_flutter/lib/src/utils/typedefs.dart b/packages/stream_chat_flutter/lib/src/utils/typedefs.dart index 582e7f7201..a22555d899 100644 --- a/packages/stream_chat_flutter/lib/src/utils/typedefs.dart +++ b/packages/stream_chat_flutter/lib/src/utils/typedefs.dart @@ -351,11 +351,11 @@ typedef UserItemBuilder = Widget Function(BuildContext, User, bool); typedef OnScrollToBottom = Function(int unreadCount); /// Widget builder for widgets that may require data from the -/// [MessageInputController]. +/// [StreamMessageComposerController]. typedef MessageRelatedBuilder = Widget Function( BuildContext context, - StreamMessageInputController messageInputController, + StreamMessageComposerController messageComposerController, ); /// A function that returns true if the message is valid and can be sent. diff --git a/packages/stream_chat_flutter/test/src/message_input/message_input_test.dart b/packages/stream_chat_flutter/test/src/message_input/message_input_test.dart index 9dee71047a..2f3b787f22 100644 --- a/packages/stream_chat_flutter/test/src/message_input/message_input_test.dart +++ b/packages/stream_chat_flutter/test/src/message_input/message_input_test.dart @@ -223,7 +223,7 @@ void main() { final quotedMessage = Message(text: 'I am a quoted message'); final initialMessage = Message(quotedMessage: quotedMessage); - final messageInputController = StreamMessageInputController( + final messageInputController = StreamMessageComposerController( message: initialMessage, ); @@ -237,7 +237,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: messageInputController, + messageComposerController: messageInputController, onQuotedMessageCleared: () { onQuotedMessageClearedCalled = true; }, @@ -271,7 +271,7 @@ void main() { final quotedMessage = Message(text: 'I am a quoted message'); final initialMessage = Message(quotedMessage: quotedMessage); - final messageInputController = StreamMessageInputController( + final messageInputController = StreamMessageComposerController( message: initialMessage, ); @@ -285,7 +285,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: messageInputController, + messageComposerController: messageInputController, onQuotedMessageCleared: () { onQuotedMessageClearedCalled = true; }, @@ -368,7 +368,7 @@ void main() { createdAt: DateTime.now(), ); - final messageInputController = StreamMessageInputController()..editMessage(existingMessage); + final messageInputController = StreamMessageComposerController()..editMessage(existingMessage); addTearDown(messageInputController.dispose); final key = GlobalKey(); @@ -383,7 +383,7 @@ void main() { bottomNavigationBar: DefaultStreamMessageComposer( key: key, props: MessageComposerProps( - messageInputController: messageInputController, + messageComposerController: messageInputController, ), ), ), @@ -410,7 +410,7 @@ void main() { (_) async => SendMessageResponse()..message = Message(text: 'Hello'), ); - final messageInputController = StreamMessageInputController( + final messageInputController = StreamMessageComposerController( message: Message(text: 'Hello'), ); addTearDown(messageInputController.dispose); @@ -427,7 +427,7 @@ void main() { bottomNavigationBar: DefaultStreamMessageComposer( key: key, props: MessageComposerProps( - messageInputController: messageInputController, + messageComposerController: messageInputController, ), ), ), @@ -535,7 +535,7 @@ void main() { 'should show DmCheckboxListTile when in a thread and hideSendAsDm is false', (tester) async { // Set up a message controller with a parent message ID (thread) - final messageInputController = StreamMessageInputController( + final messageInputController = StreamMessageComposerController( message: Message(parentId: 'parent-message-id'), ); @@ -547,7 +547,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: messageInputController, + messageComposerController: messageInputController, ), ), ), @@ -565,7 +565,7 @@ void main() { 'should toggle showInChannel value when DmCheckboxListTile is tapped', (tester) async { // Set up a message controller with a parent message ID (thread) - final messageInputController = StreamMessageInputController( + final messageInputController = StreamMessageComposerController( message: Message(parentId: 'parent-message-id'), ); @@ -582,7 +582,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: messageInputController, + messageComposerController: messageInputController, ), ), ), @@ -653,7 +653,7 @@ void main() { text: 'Original message', user: User(id: 'other-user'), ); - final controller = StreamMessageInputController( + final controller = StreamMessageComposerController( message: Message( quotedMessage: quotedMessage, quotedMessageId: quotedMessage.id, @@ -671,7 +671,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, onQuotedMessageCleared: () { onQuotedMessageClearedCalled = true; }, @@ -705,7 +705,7 @@ void main() { text: 'Original message', user: User(id: 'other-user'), ); - final controller = StreamMessageInputController( + final controller = StreamMessageComposerController( message: Message( quotedMessage: quotedMessage, quotedMessageId: quotedMessage.id, @@ -723,7 +723,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, onQuotedMessageCleared: () { onQuotedMessageClearedCalled = true; }, @@ -757,7 +757,7 @@ void main() { text: 'Original text', user: User(id: 'other-user'), ); - final controller = StreamMessageInputController( + final controller = StreamMessageComposerController( message: Message( quotedMessage: quotedMessage, quotedMessageId: quotedMessage.id, @@ -773,7 +773,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), @@ -809,7 +809,7 @@ void main() { text: 'Original text', user: User(id: 'other-user'), ); - final controller = StreamMessageInputController( + final controller = StreamMessageComposerController( message: Message( quotedMessage: quotedMessage, quotedMessageId: quotedMessage.id, @@ -825,7 +825,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), @@ -860,7 +860,7 @@ void main() { text: 'Original text', user: User(id: 'user-id'), ); - final controller = StreamMessageInputController()..editMessage(existingMessage); + final controller = StreamMessageComposerController()..editMessage(existingMessage); addTearDown(controller.dispose); await tester.pumpWidget( @@ -871,7 +871,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), @@ -908,7 +908,7 @@ void main() { text: 'Original text', user: User(id: 'user-id'), ); - final controller = StreamMessageInputController()..editMessage(existingMessage); + final controller = StreamMessageComposerController()..editMessage(existingMessage); addTearDown(controller.dispose); await tester.pumpWidget( @@ -919,7 +919,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), @@ -952,7 +952,7 @@ void main() { text: 'Being edited', user: User(id: 'user-id'), ); - final controller = StreamMessageInputController()..editMessage(existingMessage); + final controller = StreamMessageComposerController()..editMessage(existingMessage); addTearDown(controller.dispose); await tester.pumpWidget( @@ -963,7 +963,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), @@ -996,7 +996,7 @@ void main() { text: 'Being edited', user: User(id: 'user-id'), ); - final controller = StreamMessageInputController()..editMessage(existingMessage); + final controller = StreamMessageComposerController()..editMessage(existingMessage); addTearDown(controller.dispose); await tester.pumpWidget( @@ -1007,7 +1007,7 @@ void main() { channel: channel, child: Scaffold( bottomNavigationBar: StreamMessageComposer( - messageInputController: controller, + messageComposerController: controller, ), ), ), diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index 342041240b..07c87bec32 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -2,19 +2,21 @@ 🛑️ Breaking -- Renamed `StreamMessageInputController.editingOriginalMessage` → `messageBeingEdited`. -- `StreamMessageInputController` constructor no longer accepts non-initial messages; +- Renamed `StreamMessageInputController` → `StreamMessageComposerController`. +- Renamed `StreamRestorableMessageInputController` → `StreamRestorableMessageComposerController`. +- Renamed `StreamMessageComposerController.editingOriginalMessage` → `messageBeingEdited`. +- `StreamMessageComposerController` constructor no longer accepts non-initial messages; use `editMessage()` to enter edit mode. -- `StreamMessageInputController.cancelEditMessage()` is now a no-op when no edit is active. -- `StreamMessageInputController.clear()` no longer exits edit mode; +- `StreamMessageComposerController.cancelEditMessage()` is now a no-op when no edit is active. +- `StreamMessageComposerController.clear()` no longer exits edit mode; use `cancelEditMessage()` instead. ✅ Added -- Added `StreamMessageInputController.isEditing` getter. -- Added `StreamMessageInputController.clearCommand()`; setting `command = null` is +- Added `StreamMessageComposerController.isEditing` getter. +- Added `StreamMessageComposerController.clearCommand()`; setting `command = null` is now an alias for it. -- `StreamMessageInputController.editMessage()` and the `command` setter are now +- `StreamMessageComposerController.editMessage()` and the `command` setter are now re-entrant — repeated calls preserve the original restore snapshot. 🔄 Changed @@ -26,7 +28,7 @@ 🐞 Fixed - Fixed `StreamChatCore` disconnecting the WebSocket immediately on background when no `onBackgroundEventReceived` handler was provided; the keep-alive timer now fires before the connection closes regardless of whether a handler is set. -- Fixed `StreamMessageInputController.cancelEditMessage` losing the pre-edit draft when a remote update arrived for the message being edited. +- Fixed `StreamMessageComposerController.cancelEditMessage` losing the pre-edit draft when a remote update arrived for the message being edited. ## 10.0.0-beta.13 diff --git a/packages/stream_chat_flutter_core/README.md b/packages/stream_chat_flutter_core/README.md index 695cd9cdf0..82e82fdaf8 100644 --- a/packages/stream_chat_flutter_core/README.md +++ b/packages/stream_chat_flutter_core/README.md @@ -75,7 +75,7 @@ Controllers are used to handle the business logic of the chat. You can use them * StreamChannelListController * StreamUserListController * StreamMessageSearchListController -* StreamMessageInputController +* StreamMessageComposerController * LazyLoadScrollView * PagedValueListenableBuilder diff --git a/packages/stream_chat_flutter_core/example/lib/main.dart b/packages/stream_chat_flutter_core/example/lib/main.dart index 40392a8c19..15173a0bad 100644 --- a/packages/stream_chat_flutter_core/example/lib/main.dart +++ b/packages/stream_chat_flutter_core/example/lib/main.dart @@ -188,8 +188,8 @@ class MessageScreen extends StatefulWidget { } class _MessageScreenState extends State { - final StreamMessageInputController messageInputController = - StreamMessageInputController(); + final StreamMessageComposerController messageComposerController = + StreamMessageComposerController(); late final ScrollController _scrollController; final messageListController = MessageListController(); @@ -201,7 +201,7 @@ class _MessageScreenState extends State { @override void dispose() { - messageInputController.dispose(); + messageComposerController.dispose(); _scrollController.dispose(); super.dispose(); } @@ -300,7 +300,7 @@ class _MessageScreenState extends State { children: [ Expanded( child: TextField( - controller: messageInputController.textFieldController, + controller: messageComposerController.textFieldController, decoration: const InputDecoration( hintText: 'Enter your message', ), @@ -312,11 +312,11 @@ class _MessageScreenState extends State { clipBehavior: Clip.hardEdge, child: InkWell( onTap: () async { - if (messageInputController.text.isNotEmpty) { + if (messageComposerController.text.isNotEmpty) { await channel.sendMessage( - messageInputController.message, + messageComposerController.message, ); - messageInputController.clear(); + messageComposerController.clear(); if (mounted) { _updateList(); } diff --git a/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart b/packages/stream_chat_flutter_core/lib/src/stream_message_composer_controller.dart similarity index 89% rename from packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart rename to packages/stream_chat_flutter_core/lib/src/stream_message_composer_controller.dart index af0e593b5c..04cbc56b63 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_message_composer_controller.dart @@ -9,45 +9,45 @@ import 'package:stream_chat_flutter_core/src/message_text_field_controller.dart' /// A value listenable builder related to a [Message]. /// -/// Pass in a [StreamMessageInputController] as the `valueListenable`. +/// Pass in a [StreamMessageComposerController] as the `valueListenable`. typedef StreamMessageValueListenableBuilder = ValueListenableBuilder; -/// {@template stream_chat_flutter.StreamMessageInputController} +/// {@template stream_chat_flutter.StreamMessageComposerController} /// Controller for storing and mutating a [Message] value. /// {@endtemplate} -class StreamMessageInputController extends ValueNotifier { +class StreamMessageComposerController extends ValueNotifier { /// Creates a controller for an editable text field. /// /// This constructor treats a null [message] argument as if it were the empty /// message. - factory StreamMessageInputController({ + factory StreamMessageComposerController({ Message? message, Map? textPatternStyle, - }) => StreamMessageInputController._( + }) => StreamMessageComposerController._( initialMessage: message ?? Message(), textPatternStyle: textPatternStyle, ); /// Creates a controller for an editable text field from an initial [text]. - factory StreamMessageInputController.fromText( + factory StreamMessageComposerController.fromText( String? text, { Map? textPatternStyle, - }) => StreamMessageInputController._( + }) => StreamMessageComposerController._( initialMessage: Message(text: text), textPatternStyle: textPatternStyle, ); /// Creates a controller for an editable text field from initial /// [attachments]. - factory StreamMessageInputController.fromAttachments( + factory StreamMessageComposerController.fromAttachments( List attachments, { Map? textPatternStyle, - }) => StreamMessageInputController._( + }) => StreamMessageComposerController._( initialMessage: Message(attachments: attachments), textPatternStyle: textPatternStyle, ); - StreamMessageInputController._({ + StreamMessageComposerController._({ required Message initialMessage, Map? textPatternStyle, }) : assert( @@ -384,7 +384,7 @@ class StreamMessageInputController extends ValueNotifier { /// session is preserved — use [cancelEditMessage] to exit edit mode. /// /// Calling this will notify all the listeners of this - /// [StreamMessageInputController] that they need to update + /// [StreamMessageComposerController] that they need to update /// (calls [notifyListeners]). For this reason, /// this method should only be called between frames, e.g. in response to user /// actions, not during the build, layout, or paint phases. @@ -423,38 +423,38 @@ class StreamMessageInputController extends ValueNotifier { } /// A [RestorableProperty] that knows how to store and restore a -/// [StreamMessageInputController]. +/// [StreamMessageComposerController]. /// -/// The [StreamMessageInputController] is accessible via the [value] getter. +/// The [StreamMessageComposerController] is accessible via the [value] getter. /// During state restoration, -/// the property will restore [StreamMessageInputController.message] +/// the property will restore [StreamMessageComposerController.message] /// to the value it had when the restoration data it is getting restored from /// was collected. -class StreamRestorableMessageInputController extends RestorableChangeNotifier { - /// Creates a [StreamRestorableMessageInputController]. +class StreamRestorableMessageComposerController extends RestorableChangeNotifier { + /// Creates a [StreamRestorableMessageComposerController]. /// /// This constructor creates a default [Message] when no `message` argument /// is supplied. - StreamRestorableMessageInputController({Message? message}) : _initialValue = message ?? Message(); + StreamRestorableMessageComposerController({Message? message}) : _initialValue = message ?? Message(); - /// Creates a [StreamRestorableMessageInputController] from an initial + /// Creates a [StreamRestorableMessageComposerController] from an initial /// [text] value. - factory StreamRestorableMessageInputController.fromText(String? text) => - StreamRestorableMessageInputController(message: Message(text: text)); + factory StreamRestorableMessageComposerController.fromText(String? text) => + StreamRestorableMessageComposerController(message: Message(text: text)); final Message _initialValue; @override - StreamMessageInputController createDefaultValue() => StreamMessageInputController(message: _initialValue); + StreamMessageComposerController createDefaultValue() => StreamMessageComposerController(message: _initialValue); @override - StreamMessageInputController fromPrimitives(Object? data) { + StreamMessageComposerController fromPrimitives(Object? data) { final restoredData = json.decode(data! as String); final message = Message.fromJson(restoredData['message']); final state = MessageState.fromJson(restoredData['message_state']); - return StreamMessageInputController(message: message.copyWith(state: state)); + return StreamMessageComposerController(message: message.copyWith(state: state)); } @override diff --git a/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart b/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart index 2bdd25a06c..105a9ad77d 100644 --- a/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart +++ b/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart @@ -17,7 +17,7 @@ export 'src/stream_chat_core.dart'; export 'src/stream_draft_list_controller.dart'; export 'src/stream_draft_list_event_handler.dart'; export 'src/stream_member_list_controller.dart'; -export 'src/stream_message_input_controller.dart'; +export 'src/stream_message_composer_controller.dart'; export 'src/stream_message_reminder_list_controller.dart'; export 'src/stream_message_reminder_list_event_handler.dart'; export 'src/stream_message_search_list_controller.dart'; diff --git a/packages/stream_chat_flutter_core/test/stream_message_input_controller_test.dart b/packages/stream_chat_flutter_core/test/stream_message_composer_controller_test.dart similarity index 95% rename from packages/stream_chat_flutter_core/test/stream_message_input_controller_test.dart rename to packages/stream_chat_flutter_core/test/stream_message_composer_controller_test.dart index 03ef349764..4bc9062767 100644 --- a/packages/stream_chat_flutter_core/test/stream_message_input_controller_test.dart +++ b/packages/stream_chat_flutter_core/test/stream_message_composer_controller_test.dart @@ -5,17 +5,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:stream_chat/stream_chat.dart'; -import 'package:stream_chat_flutter_core/src/stream_message_input_controller.dart'; +import 'package:stream_chat_flutter_core/src/stream_message_composer_controller.dart'; class ValueNotifierListenerMock extends Mock { void call(); } void main() { - late StreamMessageInputController controller; + late StreamMessageComposerController controller; setUp(() { - controller = StreamMessageInputController(); + controller = StreamMessageComposerController(); }); tearDown(() { @@ -31,7 +31,7 @@ void main() { }); test('fromText constructor initializes with proper text', () { - final textController = StreamMessageInputController.fromText('Hello'); + final textController = StreamMessageComposerController.fromText('Hello'); expect(textController.text, 'Hello'); textController.dispose(); }); @@ -41,7 +41,7 @@ void main() { Attachment(type: 'image', title: 'test'), ]; - final controller = StreamMessageInputController.fromAttachments( + final controller = StreamMessageComposerController.fromAttachments( attachments, ); @@ -56,7 +56,7 @@ void main() { }, }; - final controller = StreamMessageInputController( + final controller = StreamMessageComposerController( textPatternStyle: patterns, ); @@ -458,13 +458,13 @@ void main() { ); expect( - () => StreamMessageInputController(message: existingMessage), + () => StreamMessageComposerController(message: existingMessage), throwsA(isA()), ); }); test('constructing with a fresh message does not enter edit mode', () { - final editController = StreamMessageInputController.fromText('Some draft'); + final editController = StreamMessageComposerController.fromText('Some draft'); addTearDown(editController.dispose); expect(editController.messageBeingEdited, isNull); @@ -526,7 +526,7 @@ void main() { }); test('cancelEditMessage restores the draft that was in the composer before edit', () { - final draftController = StreamMessageInputController.fromText('Draft text'); + final draftController = StreamMessageComposerController.fromText('Draft text'); addTearDown(draftController.dispose); draftController.editMessage(Message(id: 'msg-1', text: 'Original text')); @@ -538,7 +538,7 @@ void main() { }); test('editMessage called again during an edit keeps the original pre-edit draft', () { - final draftController = StreamMessageInputController.fromText('Draft text'); + final draftController = StreamMessageComposerController.fromText('Draft text'); addTearDown(draftController.dispose); draftController.editMessage(Message(id: 'msg-1', text: 'Original text')); @@ -552,7 +552,7 @@ void main() { }); test('cancelEditMessage without an active edit is a no-op', () { - final draftController = StreamMessageInputController.fromText('Draft text'); + final draftController = StreamMessageComposerController.fromText('Draft text'); addTearDown(draftController.dispose); draftController.cancelEditMessage(); @@ -576,7 +576,7 @@ void main() { }); test('reset restores the initial message', () { - final initialController = StreamMessageInputController( + final initialController = StreamMessageComposerController( message: Message(text: 'Initial text'), ); @@ -589,7 +589,7 @@ void main() { test('reset with resetId=false keeps the same message ID', () { final message = Message(id: 'message-id', text: 'Initial text'); - final initialController = StreamMessageInputController(message: message); + final initialController = StreamMessageComposerController(message: message); initialController.text = 'Updated text'; initialController.reset(resetId: false); @@ -649,7 +649,7 @@ void main() { }); }); - group('RestorableMessageInputController', () { + group('RestorableMessageComposerController', () { testWidgets( 'restores old state correctly', (tester) async { @@ -702,7 +702,7 @@ class _RestorableWidget extends StatefulWidget { } class _RestorableWidgetState extends State<_RestorableWidget> with RestorationMixin { - final controller = StreamRestorableMessageInputController(); + final controller = StreamRestorableMessageComposerController(); @override String get restorationId => 'widget'; diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index 830c686edd..60af1129ee 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -26,7 +26,7 @@ class ChannelPage extends StatefulWidget { class _ChannelPageState extends State { FocusNode? _focusNode; - final _messageInputController = StreamMessageInputController(); + final _messageComposerController = StreamMessageComposerController(); @override void initState() { @@ -41,14 +41,14 @@ class _ChannelPageState extends State { } void _reply(Message message) { - _messageInputController.quotedMessage = message; + _messageComposerController.quotedMessage = message; WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _focusNode!.requestFocus(); }); } void _editMessage(Message message) { - _messageInputController.editMessage(message); + _messageComposerController.editMessage(message); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _focusNode!.requestFocus(); }); @@ -121,8 +121,8 @@ class _ChannelPageState extends State { return StreamMessageComposer( focusNode: _focusNode, - messageInputController: _messageInputController, - onQuotedMessageCleared: _messageInputController.clearQuotedMessage, + messageComposerController: _messageComposerController, + onQuotedMessageCleared: _messageComposerController.clearQuotedMessage, enableVoiceRecording: true, allowedAttachmentPickerTypes: [ ...AttachmentPickerType.values, diff --git a/sample_app/lib/pages/thread_page.dart b/sample_app/lib/pages/thread_page.dart index e65a76ae67..907a749706 100644 --- a/sample_app/lib/pages/thread_page.dart +++ b/sample_app/lib/pages/thread_page.dart @@ -20,12 +20,12 @@ class ThreadPage extends StatefulWidget { class _ThreadPageState extends State { final FocusNode _focusNode = FocusNode(); - late StreamMessageInputController _messageInputController; + late StreamMessageComposerController _messageComposerController; @override void initState() { super.initState(); - _messageInputController = StreamMessageInputController( + _messageComposerController = StreamMessageComposerController( message: Message(parentId: widget.parent.id), ); } @@ -37,7 +37,7 @@ class _ThreadPageState extends State { } void _reply(Message message) { - _messageInputController.quotedMessage = message; + _messageComposerController.quotedMessage = message; WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _focusNode.requestFocus(); }); @@ -65,7 +65,7 @@ class _ThreadPageState extends State { if (widget.parent.type != 'deleted') StreamMessageComposer( focusNode: _focusNode, - messageInputController: _messageInputController, + messageComposerController: _messageComposerController, enableVoiceRecording: true, ), ],