Skip to content

Use component factory when rendering message attachments#6133

Merged
gpunto merged 7 commits intov7from
redesign/message-restructure-4
Feb 9, 2026
Merged

Use component factory when rendering message attachments#6133
gpunto merged 7 commits intov7from
redesign/message-restructure-4

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Feb 6, 2026

Goal

This PR finishes the restructuring of the message content, where instead of using attachment factories, we just delegate to the component factory.

Implementation

  • Remove MessageAttachmentsContent (which was using the attachment factories) and directly call the component factory for the remaining attachment types: links, recordings, unknown/custom
  • Removed content parameter from FileAttachmentFactory and updated examples
  • Fix image links appearing among media attachments

🎨 UI Changes

There should be no UI changes here. The redesign of audio & file attachments is coming in the next PR.

Testing

Can be tested in the sample by checking messages with different attachments

Summary by CodeRabbit

  • New Features

    • Added new attachment content customization APIs in ChatComponentFactory for audio recordings, files, links, and custom attachments.
    • Enhanced link attachment handling with structured click data callback instead of context/URL pair.
  • Breaking Changes

    • Removed MessageAttachmentsContent composable; use component factory methods instead.
    • Removed content property from AttachmentFactory; customize via new ChatComponentFactory overrides.
    • Media attachment previews now exclude link-type attachments.
  • Improvements

    • Simplified attachment factory APIs by removing explicit content parameters.
    • Consolidated link attachment overloads for a cleaner public interface.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 6, 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.68 MB -1.16 MB 🚀

@gpunto gpunto marked this pull request as ready for review February 6, 2026 16:38
@gpunto gpunto force-pushed the redesign/message-restructure-4 branch from 6591c42 to 6ca3134 Compare February 6, 2026 16:38
@gpunto gpunto requested a review from a team as a code owner February 6, 2026 16:38
@gpunto
Copy link
Contributor Author

gpunto commented Feb 9, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 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.

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

Walkthrough

This PR reorganizes attachment rendering by removing the content parameter from AttachmentFactory and exposing attachment content composition through new public methods in ChatComponentFactory. The MessageAttachmentsContent composable is deleted and replaced with separate content handlers routed via the component factory.

Changes

Cohort / File(s) Summary
Public API Surface
api/stream-chat-android-compose.api
Updated AttachmentFactory constructor to remove Function4 parameter; added AudioRecordAttachmentContent, LinkAttachmentContent, and CustomAttachmentContent to ChatComponentFactory; removed MessageAttachmentsContentKt and ComposableSingletons for GiphyAttachmentFactoryKt.
Attachment Factory Base & Content
attachments/AttachmentFactory.kt, attachments/content/LinkAttachmentContent.kt, attachments/content/MediaAttachmentContent.kt
Removed public content property from AttachmentFactory; consolidated LinkAttachmentContent to single overload with LinkAttachmentClickData callback; added hasLink filter to exclude link attachments from media previews.
Attachment Factory Implementations
attachments/factory/AudioRecordAttachmentFactory.kt, attachments/factory/FileAttachmentFactory.kt, attachments/factory/GiphyAttachmentFactory.kt, attachments/factory/LinkAttachmentFactory.kt, attachments/factory/MediaAttachmentFactory.kt, attachments/factory/UnsupportedAttachmentFactory.kt, attachments/factory/UploadAttachmentFactory.kt
Removed content parameter from AttachmentFactory constructor calls across all factory implementations, delegating content rendering to ChatComponentFactory.
Deleted & Replaced Composition
attachments/content/MessageAttachmentsContent.kt
Entire file deleted; composable function and attachment partitioning logic removed and replaced by separate content handlers in ChatComponentFactory.
Component & Theme Layer
components/messages/MessageContent.kt, theme/ChatComponentFactory.kt
Replaced MessageAttachmentsContent with FileUploadContent and state-based attachment handlers; added new public methods AudioRecordAttachmentContent, FileAttachmentContent (reordered params), LinkAttachmentContent, and CustomAttachmentContent to DefaultChatComponentFactory.
Documentation Examples
docs/kotlin/compose/guides/AddingCustomAttachments.kt, ui-guides/compose/customattachments/ChannelsActivity.kt, ui-guides/compose/customattachments/CustomChatComponentFactory.kt, ui-guides/compose/customattachments/MessagesActivity.kt, ui-guides/compose/customattachments/factory/QuotedDateAttachmentFactory.kt
Introduced CustomComponentFactory pattern implementing ChatComponentFactory; moved DateAttachmentContent to top-level; added CustomAttachmentContent override; removed QuotedDateAttachmentFactory file; updated ChatTheme componentFactory wiring in activity examples.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

compose

Suggested reviewers

  • VelikovPetar
  • andremion

Poem

🐰 Attachments hop and dance anew,
From factories old to themes so true,
Content flows through custom gates,
Links and audio find their fates,
Refactored streams in compose delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% 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 title clearly and specifically describes the main change: using component factory instead of attachment factories for message attachments, which aligns with the PR's primary restructuring objective.
Description check ✅ Passed The PR description covers the key required sections: Goal (restructuring to use component factory), Implementation (removal of MessageAttachmentsContent, removal of content parameter, fixing image links), and Testing (verification in sample app). However, some optional sections like UI Changes comparison screenshots and the contributor checklist are incomplete.

✏️ 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-4

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 (1)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt (1)

2892-2998: ⚠️ Potential issue | 🟡 Minor

Add thread/state notes to the new public KDocs.

The new attachment content entry points are public APIs and should include thread expectations and state notes.

📝 Example update (apply similarly to the other new methods)
 /**
  * Factory method for creating the content of audio recording attachments in a message.
  *
  * `@param` state State providing the context needed to render and handle interactions for the attachment.
  * `@param` modifier Modifier for styling.
+ *
+ * Threading: Called from the Compose UI thread.
+ * State: [state] represents the current message/attachment snapshot.
  */

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

🤖 Fix all issues with AI agents
In
`@stream-chat-android-docs/src/main/kotlin/io/getstream/chat/docs/kotlin/compose/guides/AddingCustomAttachments.kt`:
- Around line 171-178: The CustomAttachmentContent override in
CustomComponentFactory currently returns nothing when no "date" attachments are
present, suppressing the base behavior; update CustomAttachmentContent to call
the base implementation (super.CustomAttachmentContent(state, modifier)) when
the date-type check fails (e.g., in an else branch or after the if) so
UnsupportedAttachmentContent from the parent is rendered for non-date
attachments.

In
`@stream-chat-android-ui-guides/src/main/java/io/getstream/chat/android/guides/catalog/compose/customattachments/CustomChatComponentFactory.kt`:
- Around line 45-54: Update the KDoc for CustomChatComponentFactory to reference
ChatComponentFactory (not AttachmentFactory) and include the required public-API
notes about thread expectations and state handling: document that
CustomAttachmentContent is a composable override of
ChatComponentFactory.CustomAttachmentContent, describe the thread (UI/main) and
composable invocation expectations, and add a short note about how
AttachmentState is used/observed (e.g., immutable snapshot, do not mutate).
Ensure references to CustomChatComponentFactory, CustomAttachmentContent,
ChatComponentFactory, AttachmentState and DateAttachmentContent are present in
the KDoc and that the comment sits directly above the object declaration.
🧹 Nitpick comments (3)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt (1)

176-180: Route upload rendering through ChatTheme.componentFactory for consistency.

Right now uploads bypass the component factory, which makes upload rendering non-customizable compared to the other attachment types wired here. Consider delegating through componentFactory.FileUploadContent(...) instead.

♻️ Suggested change
-        FileUploadContent(
-            modifier = Modifier,
-            attachmentState = attachmentState,
-        )
+        componentFactory.FileUploadContent(
+            modifier = Modifier,
+            attachmentState = attachmentState,
+            onItemClick = ::onFileUploadContentItemClick,
+        )
-import io.getstream.chat.android.compose.ui.attachments.content.FileUploadContent
+import io.getstream.chat.android.compose.ui.attachments.content.onFileUploadContentItemClick
stream-chat-android-docs/src/main/kotlin/io/getstream/chat/docs/kotlin/compose/guides/AddingCustomAttachments.kt (2)

199-200: Consider firstOrNull for defensive access in example code.

attachments.first { it.type == "date" } will throw NoSuchElementException if the guard check in the caller is ever removed or bypassed. Since this is documentation that users will copy, a defensive pattern would be friendlier:

Suggested change
-    val attachment = attachmentState.message.attachments.first { it.type == "date" }
-    val formattedDate = attachment.extraData["payload"].toString()
+    val attachment = attachmentState.message.attachments.firstOrNull { it.type == "date" } ?: return
+    val formattedDate = attachment.extraData["payload"]?.toString() ?: return

The same applies to line 237 in DateAttachmentPreviewContent.


171-171: Public declarations in docs module lack KDoc.

CustomComponentFactory, dateAttachmentFactory, DateAttachmentContent, and DateAttachmentPreviewContent are public and undocumented. For a docs/example module this is likely acceptable, but since users copy-paste these snippets, a brief comment on each would help discoverability. As per coding guidelines, **/*.kt files should "Document public APIs with KDoc, including thread expectations and state notes."

Comment on lines 45 to 54
/**
* A custom [AttachmentFactory] that adds support for date attachments.
*/
object CustomChatComponentFactory : ChatComponentFactory {
@Composable
override fun CustomAttachmentContent(state: AttachmentState, modifier: Modifier) {
if (state.message.attachments.any { it.type == "date" }) {
DateAttachmentContent(state, modifier)
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix KDoc to reference ChatComponentFactory and add state/thread notes.

The current KDoc mentions AttachmentFactory and omits the required thread/state notes for a public API. Please align the KDoc with the actual type and include the notes.

📝 Suggested KDoc update
-/**
- * A custom [AttachmentFactory] that adds support for date attachments.
- */
+/**
+ * A custom [ChatComponentFactory] that adds support for date attachments.
+ *
+ * Threading: Called from the Compose UI thread.
+ * State: [state] represents the current message/attachment snapshot.
+ */
 object CustomChatComponentFactory : ChatComponentFactory {
+    /**
+     * Renders custom attachment content for date attachments.
+     *
+     * Threading: Called from the Compose UI thread.
+     * State: [state] contains the message/attachment snapshot for this item.
+     */
     `@Composable`
     override fun CustomAttachmentContent(state: AttachmentState, modifier: Modifier) {

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

🤖 Prompt for AI Agents
In
`@stream-chat-android-ui-guides/src/main/java/io/getstream/chat/android/guides/catalog/compose/customattachments/CustomChatComponentFactory.kt`
around lines 45 - 54, Update the KDoc for CustomChatComponentFactory to
reference ChatComponentFactory (not AttachmentFactory) and include the required
public-API notes about thread expectations and state handling: document that
CustomAttachmentContent is a composable override of
ChatComponentFactory.CustomAttachmentContent, describe the thread (UI/main) and
composable invocation expectations, and add a short note about how
AttachmentState is used/observed (e.g., immutable snapshot, do not mutate).
Ensure references to CustomChatComponentFactory, CustomAttachmentContent,
ChatComponentFactory, AttachmentState and DateAttachmentContent are present in
the KDoc and that the comment sits directly above the object declaration.

Copy link
Contributor

@andremion andremion left a comment

Choose a reason for hiding this comment

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

I believe there's an issue with the play button when we click to preview a video.
Not a blocker for this PR.
It can be fixed later.

Screen_recording_20260209_092339.webm

@gpunto
Copy link
Contributor Author

gpunto commented Feb 9, 2026

I believe there's an issue with the play button when we click to preview a video. Not a blocker for this PR. It can be fixed later.

Screen_recording_20260209_092339.webm

The video doesn't load for me, but I checked and I imagine you mean the play button is completely white, right? Good catch, I'll fix it in my next PR 👍

Screenshot 2026-02-09 at 10 55 10

@gpunto gpunto merged commit e2b19b5 into v7 Feb 9, 2026
13 checks passed
@gpunto gpunto deleted the redesign/message-restructure-4 branch February 9, 2026 09:58
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 9, 2026

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

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.

3 participants