refactor(ui): rework composer attachments with themes and new variants#112
refactor(ui): rework composer attachments with themes and new variants#112
Conversation
📝 WalkthroughWalkthroughThis PR replaces legacy MessageComposer attachment widgets with a new StreamMessageComposer* family, adds per-attachment theme types and StreamComponentFactory builder slots, removes the old StreamMessageTheme, updates exports, gallery widgetbook entries, and tests, and separately introduces bounded cross-axis support for StreamIntrinsicFlex (StreamIntrinsicBoundedCrossAxis) with related tests and small UX tweaks (mouse cursors, file-icon centering). ChangesMessage Composer Attachment System
StreamIntrinsicFlex — Bounded Cross-Axis & Tests
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
packages/stream_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart (1)
16-76: ⚡ Quick winAdd at least one reply-thumbnail golden scenario.
This matrix validates direction/remove states, but it doesn’t exercise the new
thumbnailslot introduced in this PR. Adding one light + one dark thumbnail case will guard the new visual path.🧪 Minimal coverage addition
children: [ + GoldenTestScenario( + name: 'incoming_with_thumbnail_no_remove', + child: _buildReplyInTheme( + StreamMessageComposerReplyAttachment( + title: const Text('Reply to John Doe'), + subtitle: const Text('We had a great time during our holiday.'), + direction: StreamReplyDirection.incoming, + onRemovePressed: null, + thumbnail: const SizedBox(width: 40, height: 40), + ), + ), + ), for (final style in StreamReplyDirection.values) GoldenTestScenario( name: '${style.name}_no_remove', @@ children: [ + GoldenTestScenario( + name: 'incoming_with_thumbnail_no_remove', + child: _buildReplyInTheme( + StreamMessageComposerReplyAttachment( + title: const Text('Reply to John Doe'), + subtitle: const Text('We had a great time during our holiday.'), + direction: StreamReplyDirection.incoming, + onRemovePressed: null, + thumbnail: const SizedBox(width: 40, height: 40), + ), + brightness: Brightness.dark, + ), + ), for (final style in StreamReplyDirection.values) GoldenTestScenario( name: '${style.name}_no_remove',🤖 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_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart` around lines 16 - 76, The golden tests for StreamMessageComposerReplyAttachment are missing coverage for the new thumbnail slot; add at least one light and one dark GoldenTestScenario that passes a non-null thumbnail widget into StreamMessageComposerReplyAttachment (use the existing _buildReplyInTheme helper and iterate over one or more StreamReplyDirection values or add a dedicated scenario), name them clearly (e.g., '${style.name}_with_thumbnail_light' and '${style.name}_with_thumbnail_dark'), and ensure the thumbnail is a simple deterministic widget (e.g., a small Icon or CircleAvatar) so the new visual path is exercised in both brightness modes.apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dart (1)
70-74: ⚡ Quick winAlign use-case naming with gallery convention.
Please rename this
Showcaseuse case to the required convention (Type/Size Variants) and keep/addReal-world Exampleas its own use case label for consistency in Widgetbook navigation.As per coding guidelines, "Component use cases should follow the naming convention: 1) Playground (interactive with knobs), 2) Type/Size Variants (all variants), 3) Real-world Example (contextual 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dart` around lines 70 - 74, The `@widgetbook.UseCase` currently named "Showcase" for the StreamMessageComposerLinkPreviewAttachment component should be renamed to "Type/Size Variants" to match gallery conventions; update the UseCase annotation name value for StreamMessageComposerLinkPreviewAttachment accordingly and ensure there is a separate `@widgetbook.UseCase` with the name "Real-world Example" (add one if missing) so the component has both "Type/Size Variants" and "Real-world Example" use cases alongside the existing "Playground" pattern.apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart (1)
51-55: ⚡ Quick winAlign this use-case title with the standard naming convention.
Please rename
ShowcasetoType/Size Variantsand keep/add a separateReal-world Exampleuse case.As per coding guidelines, "Component use cases should follow the naming convention: 1) Playground (interactive with knobs), 2) Type/Size Variants (all variants), 3) Real-world Example (contextual 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart` around lines 51 - 55, Change the widgetbook use-case names to follow the standard order: update the `@widgetbook.UseCase` annotation where type is StreamMessageComposerUnsupportedAttachment to rename the existing use-case from "Showcase" to "Type/Size Variants", and add a separate `@widgetbook.UseCase` block named "Real-world Example" (using the same type StreamMessageComposerUnsupportedAttachment) so both variants and a contextual example are present; ensure the two use-cases are adjacent and keep other annotation fields (type/path) unchanged.apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dart (1)
73-77: ⚡ Quick winNormalize the use-case name to the required convention.
Please switch this use-case label from
ShowcasetoType/Size Variants, and keep/add a dedicatedReal-world Examplecase.As per coding guidelines, "Component use cases should follow the naming convention: 1) Playground (interactive with knobs), 2) Type/Size Variants (all variants), 3) Real-world Example (contextual 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dart` around lines 73 - 77, Rename the current `@widgetbook.UseCase` name value from 'Showcase' to 'Type/Size Variants' for the StreamMessageComposerReplyAttachment use case (the annotation with type StreamMessageComposerReplyAttachment and path '[Components]/Message Composer'), and add a separate `@widgetbook.UseCase` entry named 'Real-world Example' that renders the same widget in contextual/usage form; ensure both useCase annotations remain in the file so the component follows the required Playground/Type/Size Variants/Real-world Example convention.apps/design_system_gallery/lib/components/message_composer/message_composer_file_attachment.dart (1)
72-76: ⚡ Quick winUpdate use-case naming to the expected gallery pattern.
Rename
ShowcasetoType/Size Variantsand keep/addReal-world Examplefor consistent component discovery.As per coding guidelines, "Component use cases should follow the naming convention: 1) Playground (interactive with knobs), 2) Type/Size Variants (all variants), 3) Real-world Example (contextual 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_file_attachment.dart` around lines 72 - 76, Update the widgetbook use-case naming for StreamMessageComposerFileAttachment by changing the existing `@widgetbook.UseCase` name value from "Showcase" to "Type/Size Variants" and add an additional `@widgetbook.UseCase` entry with name "Real-world Example" (type StreamMessageComposerFileAttachment) so the component follows the required Playground/Type/Size Variants/Real-world Example pattern; keep the existing type reference to StreamMessageComposerFileAttachment and ensure the new use-case includes the same or appropriate path metadata for component discovery.apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dart (1)
64-68: ⚡ Quick winUse the standard use-case label set for this component.
Replace
ShowcasewithType/Size Variantsand keep/addReal-world Exampleas a dedicated use case to match gallery conventions.As per coding guidelines, "Component use cases should follow the naming convention: 1) Playground (interactive with knobs), 2) Type/Size Variants (all variants), 3) Real-world Example (contextual 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dart` around lines 64 - 68, The UseCase annotation currently uses the label 'Showcase' for StreamMessageComposerEditMessageAttachment; update the name value to 'Type/Size Variants' and add a separate UseCase entry named 'Real-world Example' (keeping the type as StreamMessageComposerEditMessageAttachment) so the component follows the gallery naming convention (Playground, Type/Size Variants, Real-world Example).
🤖 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 `@packages/stream_core_flutter/CHANGELOG.md`:
- Around line 46-50: The changelog bullets mix legacy and new widget names which
can confuse migrations; update each bullet to include an explicit old→new
mapping (e.g., "MessageComposerFileAttachment →
StreamMessageComposerFileAttachment") and ensure every rename mention references
both the original symbol and its replacement (e.g.,
StreamMessageComposerAttachment replacing
StreamMessageComposerAttachmentContainer, MessageComposerReplyAttachment →
StreamMessageComposerReplyAttachment, MessageComposerLinkPreviewAttachment →
StreamMessageComposerLinkPreviewAttachment, MessageComposerMediaFileAttachment →
StreamMessageComposerMediaAttachment), and also clarify API changes (e.g.,
replace borderColor/borderRadius with shape: OutlinedBorder? and side:
BorderSide? and add style: StreamMessageComposerAttachmentThemeData?) so each
bullet is a direct mapping the reader can copy/paste.
In
`@packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_reply_attachment.dart`:
- Around line 228-235: The VerticalDivider instantiation in
stream_message_composer_reply_attachment (and the similar one in
stream_message_composer_edit_message_attachment) uses an unsupported radius
parameter which causes a compile error; remove the `radius:
BorderRadius.all(radius.max),` entry from the VerticalDivider constructor
(leaving width, thickness, indent, endIndent, and color) so the widget matches
Flutter's public API for VerticalDivider.
In
`@packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dart`:
- Around line 32-37: The generated lerp method for
StreamMessageComposerUnsupportedAttachmentThemeData calls an undefined helper
lerpDouble$; fix by making the helper available: either add the proper
import/export that provides lerpDouble$ (ensure the utility module is exported
into the part file's namespace) or replace the call with a known implementation
(e.g. dart:ui's lerpDouble or a locally defined double lerp helper) and update
the generator if needed so theme_extensions_builder emits the correct import or
symbol; locate the lerp method in
stream_message_composer_unsupported_attachment_theme.g.theme.dart and adjust the
symbol resolution for lerpDouble$ (or add the utility) so the code compiles.
---
Nitpick comments:
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dart`:
- Around line 64-68: The UseCase annotation currently uses the label 'Showcase'
for StreamMessageComposerEditMessageAttachment; update the name value to
'Type/Size Variants' and add a separate UseCase entry named 'Real-world Example'
(keeping the type as StreamMessageComposerEditMessageAttachment) so the
component follows the gallery naming convention (Playground, Type/Size Variants,
Real-world Example).
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dart`:
- Around line 70-74: The `@widgetbook.UseCase` currently named "Showcase" for the
StreamMessageComposerLinkPreviewAttachment component should be renamed to
"Type/Size Variants" to match gallery conventions; update the UseCase annotation
name value for StreamMessageComposerLinkPreviewAttachment accordingly and ensure
there is a separate `@widgetbook.UseCase` with the name "Real-world Example" (add
one if missing) so the component has both "Type/Size Variants" and "Real-world
Example" use cases alongside the existing "Playground" pattern.
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dart`:
- Around line 73-77: Rename the current `@widgetbook.UseCase` name value from
'Showcase' to 'Type/Size Variants' for the StreamMessageComposerReplyAttachment
use case (the annotation with type StreamMessageComposerReplyAttachment and path
'[Components]/Message Composer'), and add a separate `@widgetbook.UseCase` entry
named 'Real-world Example' that renders the same widget in contextual/usage
form; ensure both useCase annotations remain in the file so the component
follows the required Playground/Type/Size Variants/Real-world Example
convention.
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart`:
- Around line 51-55: Change the widgetbook use-case names to follow the standard
order: update the `@widgetbook.UseCase` annotation where type is
StreamMessageComposerUnsupportedAttachment to rename the existing use-case from
"Showcase" to "Type/Size Variants", and add a separate `@widgetbook.UseCase` block
named "Real-world Example" (using the same type
StreamMessageComposerUnsupportedAttachment) so both variants and a contextual
example are present; ensure the two use-cases are adjacent and keep other
annotation fields (type/path) unchanged.
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_file_attachment.dart`:
- Around line 72-76: Update the widgetbook use-case naming for
StreamMessageComposerFileAttachment by changing the existing `@widgetbook.UseCase`
name value from "Showcase" to "Type/Size Variants" and add an additional
`@widgetbook.UseCase` entry with name "Real-world Example" (type
StreamMessageComposerFileAttachment) so the component follows the required
Playground/Type/Size Variants/Real-world Example pattern; keep the existing type
reference to StreamMessageComposerFileAttachment and ensure the new use-case
includes the same or appropriate path metadata for component discovery.
In
`@packages/stream_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart`:
- Around line 16-76: The golden tests for StreamMessageComposerReplyAttachment
are missing coverage for the new thumbnail slot; add at least one light and one
dark GoldenTestScenario that passes a non-null thumbnail widget into
StreamMessageComposerReplyAttachment (use the existing _buildReplyInTheme helper
and iterate over one or more StreamReplyDirection values or add a dedicated
scenario), name them clearly (e.g., '${style.name}_with_thumbnail_light' and
'${style.name}_with_thumbnail_dark'), and ensure the thumbnail is a simple
deterministic widget (e.g., a small Icon or CircleAvatar) so the new visual path
is exercised in both brightness modes.
🪄 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: b5194090-e2d3-458f-b826-bdbb38299fa4
⛔ Files ignored due to path filters (5)
packages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_link_preview_dark_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_link_preview_light_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_custom_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_dark_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_light_matrix.pngis excluded by!**/*.png
📒 Files selected for processing (48)
apps/design_system_gallery/lib/app/gallery_app.directories.g.dartapps/design_system_gallery/lib/components/common/stream_tap_target_padding.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_media.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dartapps/design_system_gallery/lib/components/message_composer/message_composer_file_attachment.dartpackages/stream_core_flutter/CHANGELOG.mdpackages/stream_core_flutter/lib/src/components/accessories/stream_file_type_icon.dartpackages/stream_core_flutter/lib/src/components/controls/stream_remove_control.dartpackages/stream_core_flutter/lib/src/components/message_composer.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_attachment_container.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_link_preview_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_media_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_reply_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_edit_message_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_link_preview_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_media_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_reply_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_unsupported_attachment.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.g.theme.dartpackages/stream_core_flutter/lib/src/theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_link_preview_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_link_preview_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme_extensions.dartpackages/stream_core_flutter/test/components/message_composer/message_composer_attachment_link_preview_golden_test.dartpackages/stream_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart
💤 Files with no reviewable changes (7)
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_attachment_container.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_file_attachment.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_reply_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_link_preview_attachment.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_media_file_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_theme.dart
…k preview colors MessageComposerReplyAttachment and MessageComposerLinkPreviewAttachment now read colors directly from StreamColorScheme (semantic where available, brand/chrome shades otherwise) instead of the removed StreamMessageTheme/StreamMessageThemeData/StreamMessageStyle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… variants Adds per-widget themes and StreamComponentFactory builder slots for every composer attachment, introduces edit-message and unsupported variants, and unifies the leading/trailing media slot under a themed thumbnail across reply, edit-message, and link-preview previews. - Add StreamMessageComposerEditMessageAttachment and StreamMessageComposerUnsupportedAttachment with matching themes. - Theme reply/edit-message/link-preview thumbnails via thumbnailSize/ thumbnailShape/thumbnailSide; rename media (link-preview) and trailing (reply) parameters to thumbnail. - Drop the redundant "File" segment from StreamMessageComposerMediaFileAttachment, now StreamMessageComposerMediaAttachment. - Wire all seven attachment widgets into StreamComponentFactory and expose BuildContext extensions for each new theme. - Center StreamFileTypeIcon SVG inside its render box and add a click cursor to StreamRemoveControl on web/desktop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0e330cc to
e96a554
Compare
…urement Introduces a per-child marker that opts a single child of StreamIntrinsicFlex into measurement under the parent's cross-axis ceiling instead of the default unbounded constraints. This unblocks descendants that require a bounded cross-axis (shrink-wrapping viewports, Wrap, etc.) without forcing the whole column into bounded measurement, so unmarked siblings keep shrink-wrapping to their natural extent. Used in DefaultStreamReactions to wrap the bubble subtree, fixing layout failures when a message bubble contains a shrink-wrapping ListView (e.g. the voice-recording attachment playlist). When a layout failure does surface, the rendering library augments the FlutterError via informationCollector with a hint pointing at StreamIntrinsicBoundedCrossAxis, the affected StreamIntrinsicFlex identified via describeForError, a fallback diagnostic for upstream sources (UnconstrainedBox / OverflowBox), and the canonical flutter.dev/unbounded-constraints link. Cascade errors from the failed subtree are dropped so error reporters and the debug console see only the actionable failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Material wrapping the thumbnail in each composer attachment was defaulting to MaterialType.canvas, which paints an opaque background behind the thumbnail. Set type to MaterialType.transparency so the Material only contributes clipping and the thumbnail itself shows through cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
packages/stream_core_flutter/CHANGELOG.md (1)
48-52:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winClarify old→new symbol mapping in migration bullets.
Line 48 and Line 51 still read as mixed legacy/current naming (
MessageComposer*vsStreamMessageComposer*) without explicit mapping, which makes copy/paste migration error-prone. Please rewrite these bullets as direct old→new mappings for each symbol.🤖 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_core_flutter/CHANGELOG.md` around lines 48 - 52, Rewrite the migration bullets to use explicit old→new symbol mappings so copy/paste is unambiguous: list each renamed or removed symbol as "OldSymbol → NewSymbol" for StreamMessageComposerAttachmentContainer → StreamMessageComposerAttachment, MessageComposerFileAttachment → StreamMessageComposerFileAttachment, MessageComposerMediaFileAttachment → StreamMessageComposerMediaAttachment, MessageComposerLinkPreviewAttachment → StreamMessageComposerLinkPreviewAttachment, MessageComposerReplyAttachment → StreamMessageComposerReplyAttachment; also call out removed symbols StreamMessageTheme, StreamMessageThemeData, StreamMessageStyle as removed, state that MessageComposerReplyAttachment.style (ReplyStyle enum) was renamed to direction, and note that per-instance params backgroundColor and borderColor were removed in favor of style: StreamMessageComposerAttachmentThemeData? and shape/side replacing borderColor/borderRadius.packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dart (1)
32-37:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
lerpDouble$is still undefined — compile error persists from the prior review.Line 35 still calls
lerpDouble$(a.spacing, b.spacing, t)without any definition or import that provides this symbol. This is the same unresolved issue flagged in the previous review round. Please ensure the source file (stream_message_composer_unsupported_attachment_theme.dart) imports the utility thattheme_extensions_builderexpects to be in scope (typically re-exported via the annotation package), or regenerate after confirming the correct version oftheme_extensions_builder_annotationis declared inpubspec.yaml.#!/bin/bash # Confirm lerpDouble$ is or isn't provided by the annotation package fd -e dart . -path "*/theme_extensions_builder_annotation*" | head -20 # Check what the annotation package exports fd "theme_extensions_builder_annotation" packages/ --type f -e dart | xargs grep -l "lerpDouble" 2>/dev/null # Verify how other sibling generated theme files resolve lerpDouble$ (check their parent source file imports) rg -n "lerpDouble\$" packages/stream_core_flutter/lib/src/theme/ --type dart -l | head -5 | while read f; do echo "=== $f ==="; head -10 "$f" done # Check the annotation package for any lerpDouble$ export find . -path "*/theme_extensions_builder_annotation*" -name "*.dart" -exec grep -l "lerpDouble" {} \; 2>/dev/null🤖 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_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dart` around lines 32 - 37, The generated file stream_message_composer_unsupported_attachment_theme.dart calls an undefined lerpDouble$ when building StreamMessageComposerUnsupportedAttachmentThemeData; fix by either importing the package that provides lerpDouble$ (the symbol is exported by the theme_extensions_builder_annotation/tooling used by the generator) into that source or by regenerating the file after ensuring pubspec.yaml references the correct theme_extensions_builder_annotation version so the codegen emits a valid lerp helper. Concretely: confirm pubspec.yaml has the matching theme_extensions_builder_annotation version, run the codegen/build_runner to regenerate the file, or if you prefer a quick manual fix replace the lerpDouble$ call by the appropriate helper (or import that helper) so StreamMessageComposerUnsupportedAttachmentThemeData no longer references an undefined lerpDouble$.
🧹 Nitpick comments (3)
apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_media.dart (1)
119-120: 💤 Low valueLabel hardcodes the default thumbnail size
The string
'Small (56), Default (72), Medium (96), Large (128)'embeds72as the default. IfStreamMessageComposerMediaAttachmentThemeData's default size changes, this description silently becomes incorrect. Consider omitting the explicit pixel value for "Default" or driving it from the theme.🔧 Suggested tweak
- label: 'Small (56), Default (72), Medium (96), Large (128)', + label: 'Small (56×56) · Default · Medium (96×96) · Large (128×128)',🤖 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_media.dart` around lines 119 - 120, The label for _ExampleCard hardcodes "Default (72)"; update it to avoid a stale pixel value by either omitting the numeric value for "Default" or by reading the theme's default thumbnail size from StreamMessageComposerMediaAttachmentThemeData (e.g., use the theme's default size property when building the label) so the displayed text reflects the actual default size defined by StreamMessageComposerMediaAttachmentThemeData rather than a hardcoded 72.apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart (2)
73-75: 💤 Low valueAdd a
constconstructor to_BasicSection.
_BasicSectionhas no fields; aconstconstructor enables const instantiation at line 63.♻️ Proposed fix
class _BasicSection extends StatelessWidget { + const _BasicSection(); + `@override`- _BasicSection(), + const _BasicSection(),🤖 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart` around lines 73 - 75, The _BasicSection StatelessWidget lacks a const constructor even though it has no instance fields; add a const constructor to _BasicSection (e.g., const _BasicSection({Key? key}) : super(key: key);) so callers can instantiate it with const (notably the usage at line 63). Update the class declaration to include the new const constructor and ensure any instantiation sites are using const where appropriate.
73-75: 💤 Low valueAdd a
constconstructor to_BasicSection.
_BasicSectionhas no fields and is used as a plain_BasicSection()on line 63. Aconstconstructor makes the instantiation const-eligible and avoids unnecessary rebuilds.♻️ Proposed fix
class _BasicSection extends StatelessWidget { + const _BasicSection(); + `@override`- _BasicSection(), + const _BasicSection(),🤖 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 `@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart` around lines 73 - 75, The _BasicSection widget lacks a const constructor; add one (e.g. const _BasicSection({Key? key}) : super(key: key);) to the class declaration so instances can be const-constructed, and update its usages (replace _BasicSection() with const _BasicSection() where applicable) to avoid unnecessary rebuilds.
🤖 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
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart`:
- Around line 58-61: In MessageComposerAttachmentUnsupported (the widget in
message_composer_attachment_unsupported.dart) replace all hardcoded padding and
spacing integers with StreamTheme spacing tokens from the build context: change
padding: EdgeInsets.all(24) to use context.streamSpacing.xl and replace spacing:
32 with context.streamSpacing.xxl; also replace other occurrences of 16, 8, and
4 with context.streamSpacing.md, context.streamSpacing.xs, and
context.streamSpacing.xxs respectively (apply the same substitutions for the
other spacing/padding occurrences in this file, including the blocks around the
later usages mentioned in the review).
- Around line 58-61: Replace all hardcoded spacing integers (4, 8, 16, 24, 32)
in the MessageComposerAttachmentUnsupported UI with StreamTheme spacing tokens
by using context.streamSpacing instead of literal values; update the padding and
Column spacing in _Section and the paddings/gaps in _ExampleCard to pull the
appropriate token (e.g., context.streamSpacing.small/medium/large or the
project’s equivalent token names) so every layout gap (padding: const
EdgeInsets.all(24), Column spacing: 32, and other hardcoded edge/gap values)
references context.streamSpacing for consistency with StreamTheme.
---
Duplicate comments:
In `@packages/stream_core_flutter/CHANGELOG.md`:
- Around line 48-52: Rewrite the migration bullets to use explicit old→new
symbol mappings so copy/paste is unambiguous: list each renamed or removed
symbol as "OldSymbol → NewSymbol" for StreamMessageComposerAttachmentContainer →
StreamMessageComposerAttachment, MessageComposerFileAttachment →
StreamMessageComposerFileAttachment, MessageComposerMediaFileAttachment →
StreamMessageComposerMediaAttachment, MessageComposerLinkPreviewAttachment →
StreamMessageComposerLinkPreviewAttachment, MessageComposerReplyAttachment →
StreamMessageComposerReplyAttachment; also call out removed symbols
StreamMessageTheme, StreamMessageThemeData, StreamMessageStyle as removed, state
that MessageComposerReplyAttachment.style (ReplyStyle enum) was renamed to
direction, and note that per-instance params backgroundColor and borderColor
were removed in favor of style: StreamMessageComposerAttachmentThemeData? and
shape/side replacing borderColor/borderRadius.
In
`@packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dart`:
- Around line 32-37: The generated file
stream_message_composer_unsupported_attachment_theme.dart calls an undefined
lerpDouble$ when building StreamMessageComposerUnsupportedAttachmentThemeData;
fix by either importing the package that provides lerpDouble$ (the symbol is
exported by the theme_extensions_builder_annotation/tooling used by the
generator) into that source or by regenerating the file after ensuring
pubspec.yaml references the correct theme_extensions_builder_annotation version
so the codegen emits a valid lerp helper. Concretely: confirm pubspec.yaml has
the matching theme_extensions_builder_annotation version, run the
codegen/build_runner to regenerate the file, or if you prefer a quick manual fix
replace the lerpDouble$ call by the appropriate helper (or import that helper)
so StreamMessageComposerUnsupportedAttachmentThemeData no longer references an
undefined lerpDouble$.
---
Nitpick comments:
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_media.dart`:
- Around line 119-120: The label for _ExampleCard hardcodes "Default (72)";
update it to avoid a stale pixel value by either omitting the numeric value for
"Default" or by reading the theme's default thumbnail size from
StreamMessageComposerMediaAttachmentThemeData (e.g., use the theme's default
size property when building the label) so the displayed text reflects the actual
default size defined by StreamMessageComposerMediaAttachmentThemeData rather
than a hardcoded 72.
In
`@apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dart`:
- Around line 73-75: The _BasicSection StatelessWidget lacks a const constructor
even though it has no instance fields; add a const constructor to _BasicSection
(e.g., const _BasicSection({Key? key}) : super(key: key);) so callers can
instantiate it with const (notably the usage at line 63). Update the class
declaration to include the new const constructor and ensure any instantiation
sites are using const where appropriate.
- Around line 73-75: The _BasicSection widget lacks a const constructor; add one
(e.g. const _BasicSection({Key? key}) : super(key: key);) to the class
declaration so instances can be const-constructed, and update its usages
(replace _BasicSection() with const _BasicSection() where applicable) to avoid
unnecessary rebuilds.
🪄 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: f0b2d62e-2059-4202-812a-d3a3e17a8d52
⛔ Files ignored due to path filters (5)
packages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_link_preview_dark_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_link_preview_light_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_custom_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_dark_matrix.pngis excluded by!**/*.pngpackages/stream_core_flutter/test/components/message_composer/goldens/ci/message_composer_attachment_reply_light_matrix.pngis excluded by!**/*.png
📒 Files selected for processing (52)
apps/design_system_gallery/lib/app/gallery_app.directories.g.dartapps/design_system_gallery/lib/components/common/stream_intrinsic_flex.dartapps/design_system_gallery/lib/components/common/stream_tap_target_padding.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_media.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dartapps/design_system_gallery/lib/components/message_composer/message_composer_attachment_unsupported.dartapps/design_system_gallery/lib/components/message_composer/message_composer_file_attachment.dartpackages/stream_core_flutter/CHANGELOG.mdpackages/stream_core_flutter/lib/src/components/accessories/stream_file_type_icon.dartpackages/stream_core_flutter/lib/src/components/common/stream_intrinsic_flex.dartpackages/stream_core_flutter/lib/src/components/controls/stream_remove_control.dartpackages/stream_core_flutter/lib/src/components/message_composer.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_attachment_container.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_link_preview_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_media_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_reply_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_edit_message_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_file_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_link_preview_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_media_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_reply_attachment.dartpackages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_unsupported_attachment.dartpackages/stream_core_flutter/lib/src/components/reaction/stream_reactions.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.g.theme.dartpackages/stream_core_flutter/lib/src/theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_link_preview_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_link_preview_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_message_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme_extensions.dartpackages/stream_core_flutter/test/components/common/stream_intrinsic_flex_test.dartpackages/stream_core_flutter/test/components/message_composer/message_composer_attachment_link_preview_golden_test.dartpackages/stream_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart
💤 Files with no reviewable changes (7)
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_link_preview_attachment.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_file_attachment.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_media_file_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_reply_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/message_composer_attachment_container.dart
✅ Files skipped from review due to trivial changes (14)
- packages/stream_core_flutter/lib/src/components/accessories/stream_file_type_icon.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_attachment_theme.g.theme.dart
- packages/stream_core_flutter/test/components/common/stream_intrinsic_flex_test.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_file_attachment_theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_reply_attachment_theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_unsupported_attachment_theme.dart
- packages/stream_core_flutter/lib/src/theme/stream_theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_reply_attachment.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.dart
🚧 Files skipped from review as they are similar to previous changes (17)
- packages/stream_core_flutter/lib/src/components/controls/stream_remove_control.dart
- apps/design_system_gallery/lib/components/common/stream_tap_target_padding.dart
- packages/stream_core_flutter/lib/src/theme.dart
- packages/stream_core_flutter/test/components/message_composer/message_composer_attachment_reply_golden_test.dart
- packages/stream_core_flutter/lib/src/theme/stream_theme_extensions.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_media_attachment_theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_unsupported_attachment.dart
- apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_reply.dart
- packages/stream_core_flutter/lib/src/theme/stream_theme.g.theme.dart
- apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_edit_message.dart
- packages/stream_core_flutter/lib/src/theme/components/stream_message_composer_edit_message_attachment_theme.g.theme.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_media_attachment.dart
- packages/stream_core_flutter/lib/src/components/message_composer/attachment/stream_message_composer_link_preview_attachment.dart
- packages/stream_core_flutter/lib/src/factory/stream_component_factory.dart
- packages/stream_core_flutter/lib/src/components/common/stream_intrinsic_flex.dart
- apps/design_system_gallery/lib/app/gallery_app.directories.g.dart
- apps/design_system_gallery/lib/components/message_composer/message_composer_attachment_link_preview.dart
Summary
StreamComponentFactorybuilder slots andBuildContextextensions.StreamMessageComposerEditMessageAttachmentandStreamMessageComposerUnsupportedAttachment.thumbnailacross reply, edit-message, and link-preview previews (thumbnailSize/thumbnailShape/thumbnailSide).Notable breaking changes
StreamMessageComposerLinkPreviewAttachment.media→thumbnail, andStreamMessageComposerReplyAttachment.trailing→thumbnail.mediaSize/mediaShape/mediaSideon the link-preview theme tothumbnailSize/thumbnailShape/thumbnailSide.StreamMessageComposerMediaFileAttachment→StreamMessageComposerMediaAttachment(dropped the redundant "File" segment).StreamMessageTheme/StreamMessageThemeData/StreamMessageStyle; the reply and link-preview previews now read colors directly fromStreamColorScheme.Smaller changes
StreamFileTypeIconnow centers its SVG inside the icon's render box, so it stays centered when given larger constraints.StreamRemoveControlshows a click cursor on web/desktop when hovered.Test plan
melos run analyzemelos run test:fluttermelos run update:goldens) — output drifted from the constraint relaxation and the new themed thumbnail wrapping.Summary by CodeRabbit
New Features
Improvements
Documentation