Skip to content

Use component factory when rendering media attachment in messages#6124

Merged
gpunto merged 12 commits intov7from
redesign/message-restructure-2
Feb 3, 2026
Merged

Use component factory when rendering media attachment in messages#6124
gpunto merged 12 commits intov7from
redesign/message-restructure-2

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Feb 3, 2026

🎯 Goal

Continuing with the message content structural changes started in #6119, this time for media attachments.

🛠 Implementation details

  • Use component factory when rendering media attachment in messages
  • Restructure padding handling in the message
    • Attachment padding is now responsibility of each attachment. This was needed because we now have cases like "single image"/"single file" where the attachment should fill the whole message bubble instead of having a shape/padding of its own
  • Show media separately from files
  • Add filteredAttachments property to AttachmentState to avoid having to filter multiple times and simplify implementation of attachment composables

🎨 UI Changes

The most notable change is that now images & files are not shown with the file UI in case of mixed content

Before After
Screenshot_20260203_123204 Screenshot_20260203_123043

🧪 Testing

Can be checked in the sample

Summary by CodeRabbit

  • New Features

    • Added new styling properties for improved message layout consistency across attachment types.
    • Introduced media attachment content rendering with enhanced state management.
  • Improvements

    • Simplified attachment factory signatures and removed deprecated parameters.
    • Enhanced message styling with centralized padding and section spacing controls.
    • Improved attachment filtering logic for media, files, and other content types.
  • Refactor

    • Restructured attachment state handling for cleaner data flow throughout the UI layer.

@gpunto gpunto force-pushed the redesign/message-restructure-2 branch from 104591f to 54a3609 Compare February 3, 2026 11:30
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.26 MB 5.26 MB 0.00 MB 🟢
stream-chat-android-offline 5.48 MB 5.48 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.63 MB 10.62 MB -0.01 MB 🚀
stream-chat-android-compose 12.84 MB 11.69 MB -1.15 MB 🚀

@gpunto
Copy link
Contributor Author

gpunto commented Feb 3, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gpunto gpunto marked this pull request as ready for review February 3, 2026 11:56
@gpunto gpunto requested a review from a team as a code owner February 3, 2026 11:56
@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

Walkthrough

This PR refactors Stream Chat Android Compose's attachment handling by removing callback dependencies from factory constructors, centralizing message and interaction state through AttachmentState, introducing consistent message layout spacing via MessageStyling, and updating the ChatComponentFactory public API with new MediaAttachmentContent and modified MessageTextContent signatures.

Changes

Cohort / File(s) Summary
Public API Signatures
stream-chat-android-compose/api/stream-chat-android-compose.api
Updated AttachmentState constructor to include a List parameter; added MediaAttachmentContent to ChatComponentFactory interface; modified MessageTextContent signature to include Modifier as leading parameter; updated StreamAttachmentFactories.defaults signatures.
Attachment Factory & Dependency Removal
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/StreamAttachmentFactories.kt, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/factory/MediaAttachmentFactory.kt
Removed skipEnrichUrl and onMediaContentItemClick parameters from factory defaults; eliminated deprecated secondary constructor and content wiring; changed MediaAttachmentFactory to no-op constructor.
State-Driven Attachment Content
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/AudioRecordAttachmentContent.kt, FileAttachmentContent.kt, FileUploadContent.kt, GiphyAttachmentContent.kt, LinkAttachmentContent.kt, MediaAttachmentContent.kt
Replaced local destructuring and callback handling with state.message, state.isMine, and state.onLongItemClick() access; introduced filtering for file types and dynamic padding from MessageStyling; changed Message.attachments from mutable to immutable list.
Message Rendering & Layout
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt, MessageText.kt
Introduced rememberMessageInfo() to classify attachments; refactored rendering flow to use attachment type info; replaced fixed padding constants with centralized MessageStyling values.
Theme & Styling Utilities
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt, MessageStyling.kt
Added MediaAttachmentContent composable and modifier parameter to MessageTextContent; introduced four new PaddingValues properties (contentPadding, sectionsDistance, messageSectionPadding, textPadding).
Message Utility Helpers
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/MessageUtils.kt
Added shouldBeDisplayedAsFullSizeAttachment() extension function and fullSizeAttachmentTypes set for determining full-size attachment rendering eligibility.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

compose

Suggested reviewers

  • andremion
  • VelikovPetar

Poem

🐰 Attachments now flow through state so pure,
No callbacks scattered—just state to allure!
With spacing aligned and factories lean,
Messages compose like never seen. ✨
State-driven harmony, clean and bright,
This refactor hops into the light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Use component factory when rendering media attachment in messages' is directly related to the primary change in the changeset.
Description check ✅ Passed The PR description includes the Goal, Implementation details, and UI Changes sections with before/after screenshots. Testing section is present but minimal. Contributor and Reviewer checklists are not completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch redesign/message-restructure-2

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Failure to add the new IP will result in interrupted reviews.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt (1)

188-242: ⚠️ Potential issue | 🟡 Minor

Mixed attachments with different types are dropped when not uploading.

The refactoring correctly prevents re-rendering media/files—MediaAttachmentFactory and FileAttachmentFactory both have empty content() implementations. However, when a message contains mixed attachment types (e.g., images + audio recordings) without active uploads, attachments that don't match a single factory's canHandle() logic are silently dropped.

For example, a message with one image and one audio recording will:

  1. Render the image directly via componentFactory.MediaAttachmentContent()
  2. Call MessageAttachmentsContent(message) with the full message
  3. Fail to match any factory for the mixed list (MediaAttachmentFactory requires all images/video; AudioRecordAttachmentFactory requires all recordings)
  4. Fall back to UnsupportedAttachmentFactory, displaying a generic error while the recording is lost

Upload flows are unaffected—when hasUploads=true, only MessageAttachmentsContent processes the message and factories can extract relevant attachments from the full message.attachments.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/StreamAttachmentFactories.kt (1)

97-136: ⚠️ Potential issue | 🟡 Minor

Unused parameters in deprecated method.

The skipEnrichUrl (line 97) and onMediaContentItemClick (lines 104-113) parameters are still accepted and documented in KDoc but are no longer passed to MediaAttachmentFactory(). This means users providing custom values will have them silently ignored.

Consider either:

  1. Removing these parameters from the deprecated signature (breaking change, but acceptable for deprecated API), or
  2. Updating the KDoc to explicitly note these parameters are ignored in this deprecation cycle
🤖 Fix all issues with AI agents
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MessageAttachmentsContent.kt`:
- Around line 63-69: attachmentState is created with filteredAttachments =
emptyList(), which causes attachment content to render nothing; instead set
filteredAttachments to the attachments that match the chosen factory (e.g.,
filter message.attachments by the selected factory’s predicate or call the
factory’s handler method). Locate where attachmentState is constructed in
MessageAttachmentsContent.kt and replace emptyList() with the list of
attachments for the selected factory (use the existing
selectedFactory/attachmentFactory variable or call the factory’s
canHandle/matches method to filter message.attachments) so
state.filteredAttachments contains the actual attachments to render.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt`:
- Around line 163-164: Add a brief inline comment above the
`@Suppress`("LongMethod") on the DefaultMessageContent function explaining why the
suppression is necessary: note that DefaultMessageContent contains multiple
distinct conditional rendering paths for different attachment types (media,
files, quoted messages, reactions, previews), which increases method length for
clarity and to keep rendering logic co-located; document that refactoring would
split UI semantics and reduce readability. Reference: DefaultMessageContent.
🧹 Nitpick comments (6)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/GiphyAttachmentContent.kt (1)

319-346: Use @StreamPreview for Compose previews.

The preview still relies on @Preview. Please switch to the Stream preview helper to follow project conventions.

♻️ Suggested change
-@Preview(showBackground = true)
+@StreamPreview
 `@Composable`
 private fun GiphyAttachmentContentPreview() {

Based on learnings: Compose previews should use StreamPreview helpers.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/LinkAttachmentContent.kt (1)

288-315: Use @StreamPreview for Compose previews.

Please replace the @Preview annotation with the Stream preview helper to match project conventions.

♻️ Suggested change
-@Preview(showBackground = true)
+@StreamPreview
 `@Composable`
 private fun LinkAttachmentContentPreview() {

Based on learnings: Compose previews should use StreamPreview helpers.

stream-chat-android-compose/api/stream-chat-android-compose.api (4)

317-327: Potential source/binary break from reordered AttachmentState components.

filteredAttachments is inserted ahead of existing fields, shifting constructor/copy/component ordering. External destructuring or positional copy calls will break. If compatibility within v7 minors is a goal, consider appending the new field at the end (with a default) or providing a deprecated overload + migration notes.


471-472: Public API change in StreamAttachmentFactories.defaults—confirm migration path.

The signature now takes a List and removes/reshuffles callback parameters, which will break callers. Please confirm sample usage/docs are updated or keep a deprecated overload that delegates to the new signature to ease upgrades.


2840-2840: New ChatComponentFactory.MediaAttachmentContent requires implementer updates.

Adding an abstract method is binary/source breaking for custom factories. Please ensure migration guidance is included, or provide a fallback adapter/default to reduce friction for external implementers.


2919-2919: MessageTextContent signature reorder is source-breaking.

Moving Modifier to the first parameter changes positional/named call sites and custom factory implementations. Consider a deprecated overload for one release to smooth migration.

@gpunto gpunto force-pushed the redesign/message-restructure-2 branch from f6ee076 to 37e1d72 Compare February 3, 2026 15:16
@gpunto
Copy link
Contributor Author

gpunto commented Feb 3, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/AudioRecordAttachmentContent.kt (1)

140-145: ⚠️ Potential issue | 🟡 Minor

Unused parameter getCurrentUserId.

The getCurrentUserId parameter is defined but never used in the function body. Since isMine is now derived from attachmentState.isMine, this parameter appears to be dead code.

Consider deprecating or removing this parameter, or updating the KDoc to indicate it's no longer used.

🧹 Nitpick comments (3)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt (2)

1275-1291: Update KDoc to include the new modifier parameter (and param docs).

The signature now adds modifier, but the public API KDoc doesn’t reflect it. Consider updating the KDoc to list parameters (and any thread/state expectations if relevant).

📝 Suggested KDoc update
 /**
  * The default message text content.
  * Usually with extra styling and padding for the chat bubble.
+ *
+ * `@param` modifier Modifier for styling.
+ * `@param` message Message to show.
+ * `@param` currentUser The currently logged in user.
+ * `@param` onLongItemClick Handler used for long pressing on the message text.
+ * `@param` onLinkClick Handler used for clicking on a link in the message.
+ * `@param` onUserMentionClick Handler used for clicking on a user mention.
  */

As per coding guidelines: Document public APIs with KDoc, including thread expectations and state notes.


2931-2940: Add KDoc for the new public MediaAttachmentContent.

This is a new public API entry point and should be documented with parameters and any state/thread expectations.

📝 Suggested KDoc addition
+    /**
+     * Factory method for creating media attachment content.
+     *
+     * `@param` state The attachment state for the message being rendered.
+     * `@param` modifier Modifier for styling.
+     */
     `@Composable`
     public fun MediaAttachmentContent(
         state: AttachmentState,
         modifier: Modifier,
     ) {

As per coding guidelines: Document public APIs with KDoc, including thread expectations and state notes.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt (1)

800-832: Use @StreamPreview for Compose previews.
These previews still use @Preview; switch to the StreamPreview helpers for consistency.

Based on learnings: Compose previews should use StreamPreview helpers.

@gpunto gpunto force-pushed the redesign/message-restructure-2 branch from 6731eb7 to 14d8866 Compare February 3, 2026 17:00
@gpunto gpunto force-pushed the redesign/message-restructure-2 branch from 14d8866 to e7a7ba9 Compare February 3, 2026 17:16
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 3, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
58.4% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@gpunto gpunto merged commit c051e91 into v7 Feb 3, 2026
13 of 14 checks passed
@gpunto gpunto deleted the redesign/message-restructure-2 branch February 3, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants