feat(ui): factories for composer attachments#2566
feat(ui): factories for composer attachments#2566renefloor wants to merge 6 commits intofeat/design-refreshfrom
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart
Show resolved
Hide resolved
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feat/design-refresh #2566 +/- ##
=======================================================
+ Coverage 64.18% 65.07% +0.89%
=======================================================
Files 430 429 -1
Lines 26353 26017 -336
=======================================================
+ Hits 16915 16931 +16
+ Misses 9438 9086 -352 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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 (2)
packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart (1)
208-216:⚠️ Potential issue | 🟠 MajorBug: Container result is discarded —
trailingis never assigned.The
Containerwidget is created but not assigned totrailing. The image case will always result intrailingbeingnull.🐛 Proposed fix
if (image != null) { - Container( + trailing = Container( width: 40, height: 40, decoration: BoxDecoration( borderRadius: BorderRadius.all(context.streamRadius.md), image: DecorationImage(image: image, fit: BoxFit.cover), ), ); } else if (mimeType != null) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart` around lines 208 - 216, The Container built for the image is created but never assigned to the variable trailing, so trailing remains null; update the image branch in the component (where the Container with width:40, height:40, BoxDecoration and DecorationImage is constructed) to assign that Container to trailing (e.g., trailing = Container(...)) so the image is actually used, preserving existing properties like borderRadius: BorderRadius.all(context.streamRadius.md) and fit: BoxFit.cover.packages/stream_chat_flutter/lib/src/components/stream_chat_component_builders.dart (1)
16-32:⚠️ Potential issue | 🔴 CriticalBug: New builder parameters are declared but never added to the builders list.
The
messageComposerAttachmentListandmessageComposerAttachmentparameters are declared (lines 16-17) but not included in thebuilderslist. This means consumers cannot customize these components viastreamChatComponentBuilders().🐛 Proposed fix to include the new builders
if (messageWidget != null) StreamComponentBuilderExtension(builder: messageWidget), if (unreadIndicator != null) StreamComponentBuilderExtension(builder: unreadIndicator), + if (messageComposerAttachmentList != null) StreamComponentBuilderExtension(builder: messageComposerAttachmentList), + if (messageComposerAttachment != null) StreamComponentBuilderExtension(builder: messageComposerAttachment), ]; return builders;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/lib/src/components/stream_chat_component_builders.dart` around lines 16 - 32, The new parameters messageComposerAttachmentList and messageComposerAttachment are declared but never appended to the builders list; update the builders list in the streamChatComponentBuilders function to include conditionally-wrapped StreamComponentBuilderExtension entries for messageComposerAttachmentList and messageComposerAttachment (e.g., if (messageComposerAttachmentList != null) StreamComponentBuilderExtension(builder: messageComposerAttachmentList), and similarly for messageComposerAttachment) so consumers can override those components.
🧹 Nitpick comments (4)
packages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dart (1)
21-23: Consider updating test group and description names to match the widget under test.The test group is named
'StreamMessageInputAttachmentList tests'but the widget being tested is nowStreamMessageComposerAttachmentList. The same applies to test descriptions at lines 23, 47, and 80.♻️ Proposed fix for consistency
- group('StreamMessageInputAttachmentList tests', () { + group('StreamMessageComposerAttachmentList tests', () { testWidgets( - 'StreamMessageInputAttachmentList should render attachments', + 'StreamMessageComposerAttachmentList should render attachments', (WidgetTester tester) async {Similar updates needed for:
- Line 47:
'StreamMessageInputAttachmentList should call onRemovePressed callback'- Line 80:
'StreamMessageInputAttachmentList should display empty box if no attachments'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dart` around lines 21 - 23, Update the test group and its test descriptions to reference the current widget name StreamMessageComposerAttachmentList instead of StreamMessageInputAttachmentList: change the group label string (currently 'StreamMessageInputAttachmentList tests') and the test titles ('StreamMessageInputAttachmentList should render attachments', 'StreamMessageInputAttachmentList should call onRemovePressed callback', 'StreamMessageInputAttachmentList should display empty box if no attachments') to use 'StreamMessageComposerAttachmentList' so the group and all test descriptions match the widget under test.packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dart (1)
85-107: Minor optimization: consolidate track lookups.The code performs two passes over the tracks list:
.any()followed by.indexWhere(). These can be combined into a single lookup.♻️ Suggested refactor
if (attachment.type == AttachmentType.audio || attachment.type == AttachmentType.voiceRecording) { if (audioPlaylistController == null) { return const SizedBox.shrink(); } - final hasTrack = audioPlaylistController!.value.tracks.any((it) => it.key == attachment); - - if (!hasTrack) { - return const SizedBox.shrink(); - } - final trackIndex = audioPlaylistController!.value.tracks.indexWhere((it) => it.key == attachment); + if (trackIndex == -1) { + return const SizedBox.shrink(); + } return SizedBox(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dart` around lines 85 - 107, The code currently checks audioPlaylistController!.value.tracks twice using .any(...) then .indexWhere(...); replace this with a single lookup by using indexWhere once (e.g., compute trackIndex = audioPlaylistController!.value.tracks.indexWhere((it) => it.key == attachment)) and then check if trackIndex is -1 to decide to return SizedBox.shrink() or proceed to build MessageInputVoiceRecordingAttachment with controller: audioPlaylistController!, index: trackIndex, and onRemovePressed; keep the existing null check for audioPlaylistController before the lookup.packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart (1)
761-773: Consider simplifying conditional controller instantiation.The two branches duplicate most parameters. You could use a single constructor call with a spread or named parameter approach if the API supports it, or extract common params.
♻️ Suggested refactor
setState(() { final attachmentLimit = widget.attachmentLimit; - _pickerController = attachmentLimit != null - ? StreamAttachmentPickerController( - initialAttachments: _effectiveController.attachments, - initialPoll: _effectiveController.poll, - maxAttachmentCount: attachmentLimit, - maxAttachmentSize: widget.maxAttachmentSize, - ) - : StreamAttachmentPickerController( - initialAttachments: _effectiveController.attachments, - initialPoll: _effectiveController.poll, - maxAttachmentSize: widget.maxAttachmentSize, - ); + _pickerController = StreamAttachmentPickerController( + initialAttachments: _effectiveController.attachments, + initialPoll: _effectiveController.poll, + maxAttachmentSize: widget.maxAttachmentSize, + // Only pass maxAttachmentCount when limit is set + ...(attachmentLimit != null ? { maxAttachmentCount: attachmentLimit } : {}), + );Note: This depends on whether
StreamAttachmentPickerControlleraccepts null formaxAttachmentCount. If not, the current approach is fine.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart` around lines 761 - 773, The controller instantiation for _pickerController duplicates parameters across the conditional; refactor by building a single StreamAttachmentPickerController call using common arguments (initialAttachments: _effectiveController.attachments, initialPoll: _effectiveController.poll, maxAttachmentSize: widget.maxAttachmentSize) and supply maxAttachmentCount only when widget.attachmentLimit is non-null (e.g., pass widget.attachmentLimit directly if the constructor accepts null, or construct the args map/variables and include maxAttachmentCount conditionally before calling StreamAttachmentPickerController) so you eliminate the duplicated branches while keeping the same behavior.packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dart (1)
80-81: Consider moving computed getter to State class.The
_audioAttachmentsgetter performs filtering computation on the widget's data. While functional, placing computed logic directly on aStatefulWidgetis unconventional—widgets are typically just data holders. Consider moving this to the State class or computing inline where needed for clarity.♻️ Suggested refactor
class DefaultMessageComposerAttachmentList extends StatefulWidget { // ... /// Callback called when the remove button is pressed. ValueSetter<Attachment>? get onRemovePressed => props.onRemovePressed; - List<Attachment> get _audioAttachments => - attachments.where((it) => it.type == AttachmentType.audio || it.type == AttachmentType.voiceRecording).toList(); - `@override` State<DefaultMessageComposerAttachmentList> createState() => _DefaultMessageComposerAttachmentListState(); } class _DefaultMessageComposerAttachmentListState extends State<DefaultMessageComposerAttachmentList> { - late List<Attachment> _audioAttachments = widget._audioAttachments; + late List<Attachment> _audioAttachments = _computeAudioAttachments(); + + List<Attachment> _computeAudioAttachments() => + widget.attachments.where((it) => it.type == AttachmentType.audio || it.type == AttachmentType.voiceRecording).toList(); // In didUpdateWidget: - final newAudioAttachments = widget._audioAttachments; + final newAudioAttachments = _computeAudioAttachments();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dart` around lines 80 - 81, The _audioAttachments getter on the StreamMessageComposerAttachmentList widget performs filtering work on the widget class; move this computed logic into the corresponding State class (e.g., the State for StreamMessageComposerAttachmentList) or compute the filtered list inline where it's used (e.g., inside build or event handlers) so the widget remains a pure data holder; relocate the implementation of _audioAttachments (the where(... type == AttachmentType.audio || type == AttachmentType.voiceRecording) logic) into State and update all references to use the State-level member or local variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dart`:
- Around line 111-122: The post-frame callback that calls
_scrollController.animateTo can throw if the controller is not attached; wrap
the animateTo call in a safety guard (e.g., check _scrollController.hasClients
and mounted) before accessing _scrollController.position.maxScrollExtent or
calling animateTo in the callback for StreamMessageComposerAttachmentList; if
the guard fails, skip the animation. Ensure you keep the existing
addPostFrameCallback and only perform the animateTo when the controller is
valid.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dart`:
- Around line 174-178: The current builder in ValueListenableBuilder uses
state.tracks.where((it) => it.key == attachment).first which can throw
StateError if the track was removed between updates; update the lookup in the
builder (ValueListenableBuilder, controller, state, tracks, attachment, track)
to use a safe lookup such as state.tracks.firstWhereOrNull((it) => it.key ==
attachment) (collection package is available) or otherwise check for empty
result and handle the null/missing case before accessing track to avoid runtime
exceptions during rebuilds.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart`:
- Around line 493-500: The handler currently returns KeyEventResult.handled
whenever clearQuotedMessageKeyPredicate(node, event) is true even if no quote
was cleared; update the logic in the block inside stream_message_input.dart so
that after calling clearQuotedMessageKeyPredicate(node, event) you only return
KeyEventResult.handled when an actual action occurs (i.e., when
_effectiveController.message.quotedMessage != null &&
_effectiveController.text.isEmpty, you call
_effectiveController.clearQuotedMessage() and
widget.onQuotedMessageCleared?.call() and return handled); otherwise return
KeyEventResult.ignored so other widgets can process the key.
In `@packages/stream_chat_flutter/lib/stream_chat_flutter.dart`:
- Line 105: Update the test group and test descriptions to reference the new
class name StreamMessageComposerAttachmentList instead of the old
StreamMessageInputAttachmentList; locate the test file(s) that still mention
StreamMessageInputAttachmentList in group/test descriptions and replace those
strings (e.g., test group titles and test case descriptions) so they match the
actual widget under test (StreamMessageComposerAttachmentList) and avoid
breaking public API naming consistency.
---
Outside diff comments:
In
`@packages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dart`:
- Around line 208-216: The Container built for the image is created but never
assigned to the variable trailing, so trailing remains null; update the image
branch in the component (where the Container with width:40, height:40,
BoxDecoration and DecorationImage is constructed) to assign that Container to
trailing (e.g., trailing = Container(...)) so the image is actually used,
preserving existing properties like borderRadius:
BorderRadius.all(context.streamRadius.md) and fit: BoxFit.cover.
In
`@packages/stream_chat_flutter/lib/src/components/stream_chat_component_builders.dart`:
- Around line 16-32: The new parameters messageComposerAttachmentList and
messageComposerAttachment are declared but never appended to the builders list;
update the builders list in the streamChatComponentBuilders function to include
conditionally-wrapped StreamComponentBuilderExtension entries for
messageComposerAttachmentList and messageComposerAttachment (e.g., if
(messageComposerAttachmentList != null) StreamComponentBuilderExtension(builder:
messageComposerAttachmentList), and similarly for messageComposerAttachment) so
consumers can override those components.
---
Nitpick comments:
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dart`:
- Around line 80-81: The _audioAttachments getter on the
StreamMessageComposerAttachmentList widget performs filtering work on the widget
class; move this computed logic into the corresponding State class (e.g., the
State for StreamMessageComposerAttachmentList) or compute the filtered list
inline where it's used (e.g., inside build or event handlers) so the widget
remains a pure data holder; relocate the implementation of _audioAttachments
(the where(... type == AttachmentType.audio || type ==
AttachmentType.voiceRecording) logic) into State and update all references to
use the State-level member or local variable.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dart`:
- Around line 85-107: The code currently checks
audioPlaylistController!.value.tracks twice using .any(...) then
.indexWhere(...); replace this with a single lookup by using indexWhere once
(e.g., compute trackIndex =
audioPlaylistController!.value.tracks.indexWhere((it) => it.key == attachment))
and then check if trackIndex is -1 to decide to return SizedBox.shrink() or
proceed to build MessageInputVoiceRecordingAttachment with controller:
audioPlaylistController!, index: trackIndex, and onRemovePressed; keep the
existing null check for audioPlaylistController before the lookup.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart`:
- Around line 761-773: The controller instantiation for _pickerController
duplicates parameters across the conditional; refactor by building a single
StreamAttachmentPickerController call using common arguments
(initialAttachments: _effectiveController.attachments, initialPoll:
_effectiveController.poll, maxAttachmentSize: widget.maxAttachmentSize) and
supply maxAttachmentCount only when widget.attachmentLimit is non-null (e.g.,
pass widget.attachmentLimit directly if the constructor accepts null, or
construct the args map/variables and include maxAttachmentCount conditionally
before calling StreamAttachmentPickerController) so you eliminate the duplicated
branches while keeping the same behavior.
In
`@packages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dart`:
- Around line 21-23: Update the test group and its test descriptions to
reference the current widget name StreamMessageComposerAttachmentList instead of
StreamMessageInputAttachmentList: change the group label string (currently
'StreamMessageInputAttachmentList tests') and the test titles
('StreamMessageInputAttachmentList should render attachments',
'StreamMessageInputAttachmentList should call onRemovePressed callback',
'StreamMessageInputAttachmentList should display empty box if no attachments')
to use 'StreamMessageComposerAttachmentList' so the group and all test
descriptions match the widget under test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: da79dced-58ea-40b9-ab1a-bb13e2eeb3f1
📒 Files selected for processing (15)
melos.yamlpackages/stream_chat_flutter/lib/src/bottom_sheets/edit_message_sheet.dartpackages/stream_chat_flutter/lib/src/components/message_composer/message_composer_component_props.dartpackages/stream_chat_flutter/lib/src/components/message_composer/message_composer_input_header.dartpackages/stream_chat_flutter/lib/src/components/message_composer/message_composer_leading.dartpackages/stream_chat_flutter/lib/src/components/message_composer/stream_chat_message_composer.dartpackages/stream_chat_flutter/lib/src/components/stream_chat_component_builders.dartpackages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dartpackages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dartpackages/stream_chat_flutter/lib/src/message_input/stream_message_input.dartpackages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dartpackages/stream_chat_flutter/lib/stream_chat_flutter.dartpackages/stream_chat_flutter/pubspec.yamlpackages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dartpackages/stream_chat_flutter/test/src/message_input/message_input_test.dart
💤 Files with no reviewable changes (3)
- packages/stream_chat_flutter/lib/src/bottom_sheets/edit_message_sheet.dart
- packages/stream_chat_flutter/test/src/message_input/message_input_test.dart
- packages/stream_chat_flutter/lib/src/message_input/stream_message_input_attachment_list.dart
| if (oldWidget.attachments.length < widget.attachments.length) { | ||
| // If an attachment has been added, scroll to the end. | ||
| WidgetsBinding.instance.addPostFrameCallback( | ||
| (_) { | ||
| _scrollController.animateTo( | ||
| _scrollController.position.maxScrollExtent, | ||
| duration: const Duration(milliseconds: 200), | ||
| curve: Curves.easeOut, | ||
| ); | ||
| }, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Add safety check before animating scroll.
If the ScrollController is not yet attached to a scrollable (e.g., during initial build or if the ListView is unmounted), calling animateTo will throw. Consider adding a guard.
🛡️ Proposed fix
if (oldWidget.attachments.length < widget.attachments.length) {
// If an attachment has been added, scroll to the end.
WidgetsBinding.instance.addPostFrameCallback(
(_) {
+ if (!_scrollController.hasClients) return;
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
);
},
);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment_list.dart`
around lines 111 - 122, The post-frame callback that calls
_scrollController.animateTo can throw if the controller is not attached; wrap
the animateTo call in a safety guard (e.g., check _scrollController.hasClients
and mounted) before accessing _scrollController.position.maxScrollExtent or
calling animateTo in the callback for StreamMessageComposerAttachmentList; if
the guard fails, skip the animation. Ensure you keep the existing
addPostFrameCallback and only perform the animateTo when the controller is
valid.
| return ValueListenableBuilder( | ||
| valueListenable: controller, | ||
| builder: (context, state, _) { | ||
| final track = state.tracks.where((it) => it.key == attachment).first; | ||
|
|
There was a problem hiding this comment.
Potential runtime error if track is removed during rebuild.
Using .where(...).first can throw StateError if the track no longer exists in the playlist. Since this is inside a ValueListenableBuilder, the playlist state can change between rebuilds. Consider using .firstWhereOrNull or handling the empty case.
🛡️ Proposed fix
return ValueListenableBuilder(
valueListenable: controller,
builder: (context, state, _) {
- final track = state.tracks.where((it) => it.key == attachment).first;
+ final track = state.tracks.firstWhereOrNull((it) => it.key == attachment);
+ if (track == null) return const SizedBox.shrink();
return StreamVoiceRecordingAttachment(Note: firstWhereOrNull is available from the collection package which is already imported in the parent file.
📝 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.
| return ValueListenableBuilder( | |
| valueListenable: controller, | |
| builder: (context, state, _) { | |
| final track = state.tracks.where((it) => it.key == attachment).first; | |
| return ValueListenableBuilder( | |
| valueListenable: controller, | |
| builder: (context, state, _) { | |
| final track = state.tracks.firstWhereOrNull((it) => it.key == attachment); | |
| if (track == null) return const SizedBox.shrink(); | |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@packages/stream_chat_flutter/lib/src/message_input/stream_message_composer_attachment.dart`
around lines 174 - 178, The current builder in ValueListenableBuilder uses
state.tracks.where((it) => it.key == attachment).first which can throw
StateError if the track was removed between updates; update the lookup in the
builder (ValueListenableBuilder, controller, state, tracks, attachment, track)
to use a safe lookup such as state.tracks.firstWhereOrNull((it) => it.key ==
attachment) (collection package is available) or otherwise check for empty
result and handle the null/missing case before accessing track to avoid runtime
exceptions during rebuilds.
| if (widget.clearQuotedMessageKeyPredicate(node, event)) { | ||
| final hasQuote = _effectiveController.message.quotedMessage != null; | ||
| if (hasQuote && _effectiveController.text.isEmpty) { | ||
| _effectiveController.clearQuotedMessage(); | ||
| widget.onQuotedMessageCleared?.call(); | ||
| } | ||
| return KeyEventResult.handled; | ||
| } |
There was a problem hiding this comment.
Key event returns handled even when no action is taken.
When clearQuotedMessageKeyPredicate matches but there's no quoted message or text is not empty, the function still returns KeyEventResult.handled. This prevents other widgets from processing the Escape key. Consider returning ignored when no action is performed.
🛡️ Proposed fix
if (widget.clearQuotedMessageKeyPredicate(node, event)) {
final hasQuote = _effectiveController.message.quotedMessage != null;
if (hasQuote && _effectiveController.text.isEmpty) {
_effectiveController.clearQuotedMessage();
widget.onQuotedMessageCleared?.call();
+ return KeyEventResult.handled;
}
- return KeyEventResult.handled;
+ return KeyEventResult.ignored;
}
return KeyEventResult.ignored;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart`
around lines 493 - 500, The handler currently returns KeyEventResult.handled
whenever clearQuotedMessageKeyPredicate(node, event) is true even if no quote
was cleared; update the logic in the block inside stream_message_input.dart so
that after calling clearQuotedMessageKeyPredicate(node, event) you only return
KeyEventResult.handled when an actual action occurs (i.e., when
_effectiveController.message.quotedMessage != null &&
_effectiveController.text.isEmpty, you call
_effectiveController.clearQuotedMessage() and
widget.onQuotedMessageCleared?.call() and return handled); otherwise return
KeyEventResult.ignored so other widgets can process the key.
| export 'src/message_input/countdown_button.dart'; | ||
| export 'src/message_input/enums.dart'; | ||
| export 'src/message_input/quoted_message_widget.dart'; | ||
| export 'src/message_input/stream_message_composer_attachment_list.dart'; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the old file still exists (for backwards compatibility) or was deleted
fd -t f "stream_message_input_attachment_list.dart" packages/stream_chat_flutter
# Check for any remaining references to StreamMessageInputAttachmentList in the codebase
rg -n "StreamMessageInputAttachmentList" --type dartRepository: GetStream/stream-chat-flutter
Length of output: 743
🏁 Script executed:
#!/bin/bash
# Check the test file to see what it actually imports and uses
cat -n packages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dart | head -50
# Also check if StreamMessageComposerAttachmentList is used in the test
rg -n "StreamMessageComposerAttachmentList" packages/stream_chat_flutter/test/src/message_input/message_input_attachment_list_test.dartRepository: GetStream/stream-chat-flutter
Length of output: 2172
🏁 Script executed:
#!/bin/bash
# Check the current state of stream_chat_flutter.dart around line 105 to see context
sed -n '100,110p' packages/stream_chat_flutter/lib/stream_chat_flutter.dart
# Search for any other references to the old export path
rg -n "stream_message_input_attachment_list" packages/stream_chat_flutter --type dart
# Check if there was a previous file that existed
fd "stream_message_input" packages/stream_chat_flutter/libRepository: GetStream/stream-chat-flutter
Length of output: 1177
Update test descriptions to use new class name.
This is a breaking change for public API consumers who were using StreamMessageInputAttachmentList. The old file and class have been completely refactored and renamed to StreamMessageComposerAttachmentList. While the test file's actual code correctly uses the new class, the test group and test descriptions (lines 21, 23, 47, 80) still reference the old class name and should be updated for consistency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/stream_chat_flutter/lib/stream_chat_flutter.dart` at line 105,
Update the test group and test descriptions to reference the new class name
StreamMessageComposerAttachmentList instead of the old
StreamMessageInputAttachmentList; locate the test file(s) that still mention
StreamMessageInputAttachmentList in group/test descriptions and replace those
strings (e.g., test group titles and test case descriptions) so they match the
actual widget under test (StreamMessageComposerAttachmentList) and avoid
breaking public API naming consistency.
Submit a pull request
CLA
Description of the pull request
Main change in this PR is that it removes all the builder methods and only creates a factories for the attachment list or individual attachments.
It also re-adds some missing features and removes unused properties.
needs: GetStream/stream-core-flutter#83
Summary by CodeRabbit
Release Notes
New Features
Improvements
Refactor