From 0bc96f6c7dd45930eb50797bd739e918bd3b985a Mon Sep 17 00:00:00 2001 From: Gian <47775302+gpunto@users.noreply.github.com> Date: Tue, 7 Jul 2026 10:59:59 +0200 Subject: [PATCH] compose: Derive Giphy ratio from the downloaded GIF when dimensions are missing --- .../content/GiphyAttachmentContent.kt | 58 +++++++++++++++--- ...tsContentTest_giphy_attachment_content.png | Bin 9564 -> 10791 bytes 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/GiphyAttachmentContent.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/GiphyAttachmentContent.kt index 135faa3694b..8fff197138b 100644 --- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/GiphyAttachmentContent.kt +++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/attachments/content/GiphyAttachmentContent.kt @@ -31,12 +31,16 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.isSpecified import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.layout.ContentScale @@ -52,6 +56,7 @@ import coil3.compose.LocalAsyncImagePreviewHandler import io.getstream.chat.android.client.utils.attachment.isGiphy import io.getstream.chat.android.compose.R import io.getstream.chat.android.compose.state.messages.attachments.AttachmentState +import io.getstream.chat.android.compose.ui.components.ShimmerProgressIndicator import io.getstream.chat.android.compose.ui.theme.ChatTheme import io.getstream.chat.android.compose.ui.theme.StreamDimens import io.getstream.chat.android.compose.ui.util.AsyncImagePreviewHandler @@ -178,6 +183,8 @@ public fun GiphyAttachmentContent( val width = ChatTheme.dimens.attachmentsContentGiphyWidth val height = ChatTheme.dimens.attachmentsContentGiphyHeight + var downloadedRatio by remember(previewUrl) { mutableStateOf(null) } + val giphyDimensions: DpSize by remember(key1 = giphyInfo) { derivedStateOf { if (giphyInfo != null) { @@ -208,7 +215,18 @@ public fun GiphyAttachmentContent( } } } else { - DpSize(maxWidth, maxHeight) + val ratio = downloadedRatio + if (ratio == null) { + val side = minOf(maxWidth, maxHeight) + DpSize(side, side) + } else { + calculateResultingDimensions( + maxWidth = maxWidth, + maxHeight = maxHeight, + giphyWidth = ratio.dp, + giphyHeight = 1.dp, + ) + } } } } @@ -233,12 +251,38 @@ public fun GiphyAttachmentContent( onLongClick = { onLongItemClick(message) }, ), ) { - StreamAsyncImage( - data = giphyInfo?.url ?: attachment.giphyFallbackPreviewUrl, - modifier = Modifier.fillMaxSize(), - contentDescription = null, - contentScale = contentScale, - ) + if (giphyInfo == null) { + StreamAsyncImage( + data = attachment.giphyFallbackPreviewUrl, + modifier = Modifier.fillMaxSize(), + contentScale = contentScale, + ) { imageState -> + val painter = imageState.painter + val intrinsicSize = painter?.intrinsicSize + LaunchedEffect(intrinsicSize) { + if (intrinsicSize != null && intrinsicSize.isSpecified && intrinsicSize.height > 0f) { + downloadedRatio = intrinsicSize.width / intrinsicSize.height + } + } + if (painter == null) { + ShimmerProgressIndicator(modifier = Modifier.matchParentSize()) + } else { + Image( + painter = painter, + contentDescription = null, + modifier = Modifier.matchParentSize(), + contentScale = contentScale, + ) + } + } + } else { + StreamAsyncImage( + data = giphyInfo.url, + modifier = Modifier.fillMaxSize(), + contentDescription = null, + contentScale = contentScale, + ) + } Image( modifier = Modifier diff --git a/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_giphy_attachment_content.png b/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_giphy_attachment_content.png index b7868d54ce1ff67412fa5b75fe0adde8c93404c7..54eb58c74da7d902943c51ff510c2b1f36d2b74d 100644 GIT binary patch literal 10791 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 literal 9564 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 E9}=NecmMzZ