Skip to content

Update sizing of media attachments in messages#6303

Open
gpunto wants to merge 3 commits intov7from
redesign/update-media-attachment-sizing
Open

Update sizing of media attachments in messages#6303
gpunto wants to merge 3 commits intov7from
redesign/update-media-attachment-sizing

Conversation

@gpunto
Copy link
Copy Markdown
Contributor

@gpunto gpunto commented Mar 27, 2026

Goal

The sizing logic for media attachment was incorrect. They should have their wider side limited to a max of 256dp and the smaller side to 192dp.

Implementation

🎨 UI Changes

Before After
Screenshot_20260327_180452 Screenshot_20260327_180323

Testing

Check messages with media attachments to see that they match the expected size

Summary by CodeRabbit

  • New Features

    • Added message alignment configuration for improved message positioning control.
  • Bug Fixes

    • Improved media attachment sizing logic to be orientation-aware, ensuring better image and video display across different screen orientations.

@gpunto gpunto added the pr:improvement Improvement label Mar 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.86 MB 0.61 MB 🔴
stream-chat-android-ui-components 10.60 MB 11.17 MB 0.57 MB 🔴
stream-chat-android-compose 12.81 MB 12.41 MB -0.40 MB 🚀

@gpunto gpunto force-pushed the redesign/update-media-attachment-sizing branch from 5bcf28f to b10882b Compare March 30, 2026 07:29
@gpunto
Copy link
Copy Markdown
Contributor Author

gpunto commented Mar 30, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 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
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Walkthrough

This PR introduces message alignment support throughout the message rendering pipeline. The changes add a MessageAlignment parameter to MessageContent and MessageRegularContentParams, compute alignment from the theme provider, and apply it to control horizontal layout in message rendering. Additionally, media attachment sizing logic is refactored to use orientation-based dimensions.

Changes

Cohort / File(s) Summary
Message Alignment Core
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt
Added messageAlignment parameter to public MessageContent and internal DefaultMessageContent composables; applied alignment to Column(horizontalAlignment = messageAlignment.contentAlignment) for message content layout.
Message Alignment Routing
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageContainer.kt, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
Updated RegularMessageContent to compute alignment from ChatTheme.messageAlignmentProvider and forward it to MessageContent and DefaultMessageContent.
Message Alignment Parameters
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt
Extended MessageRegularContentParams data class with new required messageAlignment: MessageAlignment property.
Media Attachment Sizing
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt
Replaced video/image-dependent height calculation with orientation-based bounding-box sizing; introduced singleMediaAttachmentSize(aspectRatio) function returning fixed dimensions (256×192 landscape, 192×256 portrait, 256×256 square).
Public API Updates
stream-chat-android-compose/api/stream-chat-android-compose.api
Updated exported API signatures for MessageContent and MessageRegularContentParams to reflect MessageAlignment parameter additions.

Sequence Diagram(s)

sequenceDiagram
    participant MessageContainer as MessageContainer<br/>(Composable)
    participant Theme as ChatTheme
    participant Provider as messageAlignmentProvider
    participant MessageContent as MessageContent<br/>(Composable)
    participant DefaultMessageContent as DefaultMessageContent<br/>(Composable)
    participant Layout as Column Layout

    MessageContainer->>Theme: Access ChatTheme
    Theme->>Provider: Query messageAlignmentProvider
    Provider-->>Theme: Return MessageAlignment
    Theme-->>MessageContainer: Receive alignment
    MessageContainer->>MessageContent: Call with messageAlignment
    MessageContent->>DefaultMessageContent: Pass messageAlignment param
    DefaultMessageContent->>Layout: Apply alignment to Column<br/>(horizontalAlignment)
    Layout-->>DefaultMessageContent: Render aligned message content
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hops through alignment with grace so fine,
Messages now follow the proper line!
Theme provides direction, composables receive,
Orientation-aware sizing—oh what we achieve! ✨
A rabbit's delight in structure and flow.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes a clear Goal section and before/after screenshots, but lacks Implementation details, comprehensive testing instructions, and most contributor/reviewer checklist items. Add implementation details explaining the sizing approach, expand testing section with specific test cases, and complete the contributor checklist items.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: updating media attachment sizing logic in messages, which aligns with the primary modification in MediaAttachmentContent.kt.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch redesign/update-media-attachment-sizing

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
Copy Markdown

@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: 1

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)

71-97: ⚠️ Potential issue | 🟡 Minor

Add missing KDoc for the new messageAlignment public parameter.

MessageContent now exposes messageAlignment, but the KDoc block doesn’t describe it.

💡 Suggested doc patch
 /**
  * Represents the default message content within the bubble that can show different UI based on the message state.
  *
  * `@param` message The message to show.
  * `@param` currentUser The currently logged in user.
  * `@param` modifier Modifier for styling.
  * `@param` onLongItemClick Handler when the item is long clicked.
  * `@param` onGiphyActionClick Handler for Giphy actions.
  * `@param` onQuotedMessageClick Handler for quoted message click action.
+ * `@param` messageAlignment The horizontal alignment of regular message content within the bubble.
  * `@param` onLinkClick Handler for clicking on a link in the message.
  * `@param` onMediaGalleryPreviewResult Handler when the user selects an option in the Media Gallery Preview screen.
  * `@param` giphyEphemeralContent Composable that represents the default Giphy message content.
  * `@param` deletedMessageContent Composable that represents the default content of a deleted message.
  * `@param` regularMessageContent Composable that represents the default regular message content, such as attachments and
  * text.
  */
As per coding guidelines: "`**/*.kt`: Document public APIs with KDoc, including thread expectations and state notes".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt`
around lines 71 - 97, The KDoc for the public composable MessageContent is
missing documentation for the new parameter messageAlignment; update the KDoc
block above the MessageContent function to add an `@param` entry describing
messageAlignment (its type MessageAlignment, what it controls—bubble
alignment/start vs end, default behavior MessageAlignment.Start—and any
thread/state expectations or side effects), ensuring the `@param` is consistent
with other parameter descriptions and follows project KDoc conventions.
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt (1)

798-807: ⚠️ Potential issue | 🟠 Major

Add changelog entry for MessageRegularContentParams constructor change.

The messageAlignment parameter added to MessageRegularContentParams is not yet documented in CHANGELOG.md. Add an entry to the unreleased stream-chat-android-compose section documenting this breaking API change so integrators can quickly identify and address it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt`
around lines 798 - 807, Add a changelog entry documenting the breaking API
change: the MessageRegularContentParams data class now includes a new
messageAlignment parameter. Update CHANGELOG.md in the unreleased
"stream-chat-android-compose" section with a short bullet under "Changed" (or
"Breaking changes") that names MessageRegularContentParams and describes the new
required parameter so integrators know to update their usages.
🧹 Nitpick comments (1)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt (1)

649-668: Please lock the new ratio branches down with a snapshot test.

This change introduces distinct landscape / portrait / square sizing paths, so a Paparazzi case for ratios like 1f, 1.1f, and 0.9f would make future UI regressions much easier to catch.

Based on learnings: Applies to /stream-chat-android-compose//*Test.kt : Add Paparazzi snapshots for Compose UI regressions and run verifyPaparazziDebug.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt`
around lines 649 - 668, Add Paparazzi snapshot tests that lock the three sizing
branches of singleMediaAttachmentSize by rendering a Compose component that uses
singleMediaAttachmentSize with aspect ratios 1f (square), 1.1f (landscape), and
0.9f (portrait) and verifying their layouts; create tests in a Compose test
class (e.g., MediaAttachmentContentTest) asserting snapshots for each ratio and
run verifyPaparazziDebug to commit the golden images so future changes to
singleMediaAttachmentSize (and related UI in MediaAttachmentContent composables)
will be caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Line 1669: The public API change inserts MessageAlignment into MessageContent
and reorders MessageRegularContentParams so messageAlignment is now
component3(), which breaks implementations of
ChatComponentFactory.MessageRegularContent that rely on prior positional args or
destructuring; update the repository docs (CHANGELOG.md or add
MIGRATION_TO_V7.md) to document the breaking change and provide concrete
migration steps: explain that MessageAlignment must be accepted as a new
parameter in MessageContent call sites and component constructors, show how to
update destructuring (or replace with named parameters) to account for the new
third position, and include example before/after snippets and note the same
update applies to the other occurrences referenced (around the same API region).

---

Outside diff comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt`:
- Around line 71-97: The KDoc for the public composable MessageContent is
missing documentation for the new parameter messageAlignment; update the KDoc
block above the MessageContent function to add an `@param` entry describing
messageAlignment (its type MessageAlignment, what it controls—bubble
alignment/start vs end, default behavior MessageAlignment.Start—and any
thread/state expectations or side effects), ensuring the `@param` is consistent
with other parameter descriptions and follows project KDoc conventions.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt`:
- Around line 798-807: Add a changelog entry documenting the breaking API
change: the MessageRegularContentParams data class now includes a new
messageAlignment parameter. Update CHANGELOG.md in the unreleased
"stream-chat-android-compose" section with a short bullet under "Changed" (or
"Breaking changes") that names MessageRegularContentParams and describes the new
required parameter so integrators know to update their usages.

---

Nitpick comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt`:
- Around line 649-668: Add Paparazzi snapshot tests that lock the three sizing
branches of singleMediaAttachmentSize by rendering a Compose component that uses
singleMediaAttachmentSize with aspect ratios 1f (square), 1.1f (landscape), and
0.9f (portrait) and verifying their layouts; create tests in a Compose test
class (e.g., MediaAttachmentContentTest) asserting snapshots for each ratio and
run verifyPaparazziDebug to commit the golden images so future changes to
singleMediaAttachmentSize (and related UI in MediaAttachmentContent composables)
will be caught.
🪄 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: c8734775-ba13-4eb5-a593-afb1ccb046ab

📥 Commits

Reviewing files that changed from the base of the PR and between 8a7a697 and b10882b.

⛔ Files ignored due to path filters (1)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_single_media_attachment_content.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/MediaAttachmentContent.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageContent.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageContainer.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt

@gpunto gpunto marked this pull request as ready for review March 30, 2026 08:05
@gpunto gpunto requested a review from a team as a code owner March 30, 2026 08:05
400.dp
} else {
600.dp
private fun singleMediaAttachmentSize(aspectRatio: Float): DpSize = when {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Now that we have somewhat fixed dimensions for the image, is it possible to also size the loading item in the same way (currently it seems it is always displayed as 256x256)?
I didn't look too much in how difficult this would be to extract the width/height from local files, but perhaps it is something that we can consider as an improvement in the future!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I also don't know what it'd take, but let me see!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added a step to resolve originalWidth/Height locally when resolving attachment files so they're always there even during upload

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Awesome, thank you very much! I assume this doesn't cause any StrictMode violations, or should we run it on a background scope?

Copy link
Copy Markdown
Contributor Author

@gpunto gpunto Mar 31, 2026

Choose a reason for hiding this comment

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

We are fine because resolveAttachmentFiles (which calls this new function) is marked with @WorkerThread and is executed with the IO dispatcher at the usage sites.

TBH the usage is a bit confusing because resolveAttachmentFiles is passed around as a suspend lambda, which would signal that it's safe to call from any thread. As an improvement I think we could make it suspend at the source and set the correct dispatcher, but I guess that could be a different PR. WDYT?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh I missed that part sorry. Of course, no need to cram it in this PR. BTW I just realised, since we are calculating the oh/ow on Attachment level - are those values submitted to the BE as well? (for example in sendMessage) Is it possible that this breaks some of the existing behaviour?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So, this is the summary as I understand it (with Claude's help exploring the backend codebase):

The values now get effectively sent to the bakcend when we send the message, but this shouldn't be problematic because the scenario is:

  1. The SDK uploads files to CDN, getting back a URL that contains ow/oh
  2. The message is then sent with both the CDN URL and the locally-resolved dimensions
  3. The backend overwrites original_width/original_height by extracting them from the CDN URL during RefreshMessageAttachmentURLs()

So the locally-resolved values are transient (and they should be correct while they exist). Still, we could reset them to null in augmentAttachmentOnSuccess, but that sounds a bit confusing to me

@gpunto gpunto force-pushed the redesign/update-media-attachment-sizing branch from 173f43b to 7fb0c77 Compare March 31, 2026 08:38
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
39.3% 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

pr:improvement Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants