From dbd51ebc9012686db954bf91555a9eec1edef8e1 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 31 Mar 2026 16:57:37 +0200 Subject: [PATCH] Try fixing location pin previews (#6495) * Try fixing location pin previews * Update screenshots --------- Co-authored-by: ElementBot Co-authored-by: Benoit Marty --- .../designsystem/components/LocationPin.kt | 57 ++++++++++++------- ....impl.share_ShareLocationView_Day_5_en.png | 4 +- ...mpl.share_ShareLocationView_Night_5_en.png | 4 +- ...system.components_LocationPin_Day_0_en.png | 4 +- ...stem.components_LocationPin_Night_0_en.png | 4 +- 5 files changed, 46 insertions(+), 27 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt index af8e29d518..9e783d605c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt @@ -32,9 +32,13 @@ import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp +import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.createBitmap +import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.withSave import coil3.Image import coil3.ImageLoader @@ -50,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.utils.CommonDrawables private val PIN_WIDTH = 42.dp private val PIN_HEIGHT = PIN_WIDTH * 1.2f @@ -99,21 +104,33 @@ fun LocationPin( fun rememberLocationPinBitmap(variant: PinVariant): ImageBitmap? { val context = LocalContext.current val density = LocalDensity.current - val imageLoader = SingletonImageLoader.get(context) val colors = pinColors(variant) val cacheKey = rememberCacheKey(variant) - return produceState(initialValue = null, cacheKey) { - val memoryCacheKey = MemoryCache.Key(cacheKey) - val cached = imageLoader.memoryCache?.get(memoryCacheKey) - if (cached != null) { - value = cached.image.toBitmap().asImageBitmap() - } else { - val dimensions = PinDimensions(density) - val bitmap = LocationPinRenderer.renderPin(variant, colors, dimensions, context, imageLoader) - imageLoader.memoryCache?.set(memoryCacheKey, MemoryCache.Value(bitmap.asImage())) - value = bitmap.asImageBitmap() - } - }.value + val resources = LocalResources.current + + return if (LocalInspectionMode.current) { + // In preview mode, skip async loading and return a simple placeholder image instead to avoid using ImageLoader + val dimensions = PinDimensions(density) + val avatarImage = ResourcesCompat.getDrawable(resources, CommonDrawables.sample_avatar, context.theme)?.toBitmap()?.asImage() + LocationPinRenderer.renderPin(variant, colors, dimensions, avatarImage).asImageBitmap() + } else { + produceState(initialValue = null, cacheKey) { + val imageLoader = SingletonImageLoader.get(context) + val memoryCacheKey = MemoryCache.Key(cacheKey) + val cached = imageLoader.memoryCache?.get(memoryCacheKey) + if (cached != null) { + value = cached.image.toBitmap().asImageBitmap() + } else { + val dimensions = PinDimensions(density) + val bitmap = with(LocationPinRenderer) { + val avatarImage = loadAvatarImage(variant, context, imageLoader) + renderPin(variant, colors, dimensions, avatarImage) + } + imageLoader.memoryCache?.set(memoryCacheKey, MemoryCache.Value(bitmap.asImage())) + value = bitmap.asImageBitmap() + } + }.value + } } @Composable @@ -208,19 +225,17 @@ private object LocationPinRenderer { /** * Renders a pin variant to bitmap. Suspending for async avatar loading. */ - suspend fun renderPin( + fun renderPin( variant: PinVariant, colors: PinColors, dimensions: PinDimensions, - context: Context, - imageLoader: ImageLoader, + avatarImage: Image?, ): Bitmap { val bitmap = createBitmap(dimensions.pinWidth.toInt(), dimensions.pinHeight.toInt()) val canvas = Canvas(bitmap) canvas.drawPinShape(colors.fill, colors.stroke, dimensions) when (variant) { is PinVariant.UserLocation -> { - val avatarImage = loadAvatarImage(variant.avatarData, context, imageLoader) canvas.drawAvatar( avatarImage = avatarImage, avatarData = variant.avatarData, @@ -284,11 +299,15 @@ private object LocationPinRenderer { return path } - private suspend fun loadAvatarImage( - avatarData: AvatarData, + suspend fun loadAvatarImage( + variant: PinVariant, context: Context, imageLoader: ImageLoader, ): Image? { + val avatarData = when (variant) { + is PinVariant.UserLocation -> variant.avatarData + else -> return null + } val request = ImageRequest.Builder(context) .data(avatarData) // Disable hardware rendering for Canvas diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png index 69aea3df2a..74d6ac15ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ba1418b5d42a56db47e7cc574cedb886c75d9cf22828341bd954a4f1845670e -size 17925 +oid sha256:2621fef4175ad0f0982270284ffbbdb6b3b0534b09013c1cc378504a85d13068 +size 22385 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png index 060f25819e..d79bfca142 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d786937d790e13b53a5de8ae3321e5aa8744a979a3a99ecc36def6b7dbf6cf60 -size 17237 +oid sha256:69bcf19161f70c27256c1bf0e5b99c993c86dd3e77a42d0e87061730a5c0c752 +size 21649 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png index fcc2640262..c049cff102 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d8c17c2e421452f57e4679111569054e1ed1bacc952cc1df4c7efe1f67c47ef -size 13158 +oid sha256:ca6415ca7f858146a4c00e2fa1d9602fd9f3d42c0c8ba9830e121769af80676a +size 17255 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png index dac3588ed9..8074748111 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9767298a096be7fc78210245e6b806a72a6c1ad16d7335e0f89728bbcf08ebd4 -size 15884 +oid sha256:d89b754907f98ef1df2cf227ec535cdad91dc15e90b4915039be39d8b2ae2ebd +size 16721