refactor(ui): rework composer attachments with themes and new variants#112
refactor(ui): rework composer attachments with themes and new variants#112
Conversation
|
Caution Review failedFailed to post review comments 📝 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 Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (42.79%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #112 +/- ##
==========================================
- Coverage 31.38% 30.82% -0.56%
==========================================
Files 163 171 +8
Lines 6319 6559 +240
==========================================
+ Hits 1983 2022 +39
- Misses 4336 4537 +201 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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>
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