compose: Render no-caption voice message replies on the bubble background#6552
compose: Render no-caption voice message replies on the bubble background#6552andremion wants to merge 5 commits into
Conversation
…ound A voice message reply with no caption showed its player in the darker attachment card, because shouldBeDisplayedAsFullSizeAttachment() returns false for replies. Gate the darker card on caption presence instead, so a no-caption reply renders the player on the message bubble background and a captioned one keeps the card. Extract the stateless AudioRecordAttachmentContentItems so the reply states can be previewed and snapshot-tested.
The no-caption reply player already renders on the bubble background, but it still carried the attachment-card section padding, which belongs only when the player is a card sharing the bubble with a caption. Gate the section padding on caption presence so the no-caption player uses only its own content padding, matching the design.
|
@CodeRabbit review |
✅ Action performedReview finished.
|
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
WalkthroughAudioRecordAttachmentContent now hoists AudioPlayerState collection to the parent composable and passes it with playback callbacks down to child items, replacing direct viewModel access. Padding logic switches to caption-based checks. MessageContent adjusts bottom spacer for recordings without text. New reply preview composables and tests were added. ChangesAudio record attachment refactor
Estimated code review effort: 2 (Simple) | ~15 minutes Sequence Diagram(s)sequenceDiagram
participant AudioRecordAttachmentContent
participant ViewModel
participant AudioRecordAttachmentContentItems
participant AudioRecordAttachmentContentItem
AudioRecordAttachmentContent->>ViewModel: collectAsStateWithLifecycle(state)
AudioRecordAttachmentContent->>AudioRecordAttachmentContentItems: pass playerState, callbacks
AudioRecordAttachmentContentItems->>AudioRecordAttachmentContentItem: pass onPlayToggleClick, onPlaySpeedClick, onThumbDragStart, onThumbDragStop
AudioRecordAttachmentContentItem-->>ViewModel: trigger playback action via callback
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt`:
- Around line 306-307: The bottom-padding guard in MessageContent should account
for custom/unknown attachments in addition to recordings, since
`recordingSuppliesBottomPadding` currently only checks `info.hasRecordings` and
`message.text.isEmpty()`. Update the logic around
`recordingSuppliesBottomPadding` and the `!info.displaysFullSizeAttachment`
condition so that a no-caption recording combined with later custom attachments
still keeps the spacer when `CustomAttachmentContent` is rendered last. Use the
existing attachment flags in `MessageContent`/`info` (especially `hasUnknown`)
to decide when the last attachment still needs bottom inset.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: db97add8-67c9-4979-8d80-6461c03c0729
⛔ Files ignored due to path filters (2)
stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_audio_record_reply_with_caption.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_audio_record_reply_without_caption.pngis excluded by!**/*.png
📒 Files selected for processing (4)
stream-chat-android-compose/api/stream-chat-android-compose.apistream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/AudioRecordAttachmentContent.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/attachments/content/AttachmentsContentTest.kt
…eplies A voice recording supplies its own bottom padding, unlike media and file sections which rely on the bubble's shared bottom spacer. When a no-caption voice recording was the trailing content, the player's bottom padding and the spacer stacked and doubled the bottom inset. Skip the spacer in that case so the bubble bottom matches the design.
4c34fbd to
e26fc58
Compare
Render the no-caption, caption, and recording-plus-custom-attachment reply cases through MessageContainer, exercising the bubble bottom-spacer logic and the viewModel-backed audio recording content that the Paparazzi snapshots cannot reach.
gpunto
left a comment
There was a problem hiding this comment.
Just a doubt if this change should be propagated to other attachment types
| val shouldBeFullSize = attachmentState.message.shouldBeDisplayedAsFullSizeAttachment() | ||
| val hasCaption = attachmentState.message.text.isNotEmpty() |
There was a problem hiding this comment.
Does this mean that now voice recording attachments diverge from other attachment types? e.g. a file attachment will still be rendered with the background in the quoted message case, right?
There was a problem hiding this comment.
Yes, on purpose, only the voice player drops the background when there's no caption; file and media replies keep theirs.
Here are the Figma specs https://www.figma.com/design/BJppI3JYlPy3XeEu5MZY1E/SDK-Components-Library?node-id=4011-115610&m=dev
|


Goal
When a voice message reply has no caption, the player rendered inside the darker attachment card and carried the attachment section padding plus the bubble's bottom spacer, instead of sitting on the message bubble background like a standalone voice message. The finalized Figma Reply States show a no-caption voice reply on the bubble background with no card, so this aligns the Compose SDK with the design.
The quoted (replied-to) preview keeps its darker attachment background, which is correct per the same spec, only the reply's own player was wrong.
Resolves AND-1288
Implementation
AudioRecordAttachmentContent: gate the player's darker attachment card and its section padding on caption presence (hasCaption). A no-caption reply renders on the bubble background with only the player's own content padding; a captioned reply keeps the card, and the caption provides the bottom padding. Extracted a statelessAudioRecordAttachmentContentItemsso the reply states can be previewed and snapshot-tested.MessageContent: skip the bubble's bottom spacer when the trailing content is a no-caption voice recording, which already supplies its own bottom padding. Media and file sections have no bottom padding of their own, so they still rely on the shared spacer.🎨 UI Changes
Voice message reply without a caption, in the message list. Before, the player sits in the darker attachment card with extra inset and a doubled bottom padding; after, it sits on the bubble background like a standalone voice message. A captioned voice reply is unchanged (it keeps the card).
Testing
Unit tests: added
audio record reply without captionandaudio record reply with captionPaparazzi snapshots toAttachmentsContentTest, covering the no-card and card states.Summary by CodeRabbit
New Features
Bug Fixes
Tests