From 8145727173859c51675bf47bdb6ca72ea1ef471f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Wed, 3 Sep 2025 12:39:11 +0200 Subject: [PATCH 1/2] Ensure any callback action called from the CoilStreamImageLoader is run on the caller thread --- .../images/internal/CoilStreamImageLoader.kt | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/internal/CoilStreamImageLoader.kt b/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/internal/CoilStreamImageLoader.kt index feb17db0b0e..5aa371e112e 100644 --- a/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/internal/CoilStreamImageLoader.kt +++ b/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/internal/CoilStreamImageLoader.kt @@ -46,6 +46,8 @@ import io.getstream.chat.android.ui.common.helper.DefaultImageHeadersProvider import io.getstream.chat.android.ui.common.helper.ImageAssetTransformer import io.getstream.chat.android.ui.common.helper.ImageHeadersProvider import io.getstream.chat.android.ui.common.images.internal.StreamCoil.streamImageLoader +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext internal object CoilStreamImageLoader : StreamImageLoader { @@ -146,10 +148,12 @@ internal object CoilStreamImageLoader : StreamImageLoader { transformation: StreamImageLoader.ImageTransformation, onStart: () -> Unit, onComplete: () -> Unit, - ) { + ): Unit = coroutineScope { val context = target.context - val drawable = withContext(DispatcherProvider.IO) { + val calledContext = coroutineContext + + withContext(DispatcherProvider.IO) { val asset = data.transformedAsset() val headers = asset?.toString()?.let { url -> imageHeadersProvider.getImageRequestHeaders(url).toNetworkHeaders() @@ -162,27 +166,28 @@ internal object CoilStreamImageLoader : StreamImageLoader { .error(placeholderDrawable) .data(asset) .listener( - onStart = { onStart() }, - onCancel = { onComplete() }, - onError = { _, _ -> onComplete() }, - onSuccess = { _, _ -> onComplete() }, + onStart = { launch(calledContext) { onStart() } }, + onCancel = { launch(calledContext) { onComplete() } }, + onError = { _, _ -> launch(calledContext) { onComplete() } }, + onSuccess = { _, _ -> launch(calledContext) { onComplete() } }, ) .applyTransformation(transformation) .build(), ) result.image?.asDrawable(context.resources) - } ?: return - - if (drawable is ScaleDrawable && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && drawable.child is AnimatedImageDrawable - ) { - (drawable.child as AnimatedImageDrawable).start() - } else if (drawable is MovieDrawable) { - drawable.start() + }?.let { drawable -> + launch(calledContext) { + if (drawable is ScaleDrawable && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && drawable.child is AnimatedImageDrawable + ) { + (drawable.child as AnimatedImageDrawable).start() + } else if (drawable is MovieDrawable) { + drawable.start() + } + target.setImageDrawable(drawable) + } } - - target.setImageDrawable(drawable) } override fun loadVideoThumbnail( From 44a5a3e5b4d7052af42ae9ed2f301eb661c4c4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Wed, 3 Sep 2025 15:06:13 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad0bd3b4c54..4f2fab8e329 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ ## stream-chat-android-ui-common ### 🐞 Fixed +- Ensure any callback action called from the CoilStreamImageLoader is run on the caller thread. [#5915](https://github.com/GetStream/stream-chat-android/pull/5915) ### ⬆️ Improved