Merge pull request #6954 from element-hq/fix/try-fixing-flaky-location-timeline-item-screenshots

Try fixing flaky screenshots for location timeline items
This commit is contained in:
Benoit Marty
2026-06-10 14:44:39 +02:00
committed by GitHub
13 changed files with 65 additions and 45 deletions
@@ -8,6 +8,7 @@
package io.element.android.features.location.api package io.element.android.features.location.api
import android.graphics.Bitmap
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraints
@@ -24,13 +25,17 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.graphics.createBitmap
import coil3.Extras import coil3.Extras
import coil3.asImage
import coil3.compose.AsyncImagePainter import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter import coil3.compose.rememberAsyncImagePainter
import coil3.request.ImageRequest import coil3.request.ImageRequest
import coil3.request.SuccessResult
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.features.location.api.internal.StaticMapPlaceholder import io.element.android.features.location.api.internal.StaticMapPlaceholder
import io.element.android.features.location.api.internal.StaticMapUrlBuilder import io.element.android.features.location.api.internal.StaticMapUrlBuilder
@@ -39,6 +44,7 @@ import io.element.android.libraries.designsystem.components.LocationPin
import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.PinVariant
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.utils.CommonDrawables
/** /**
* Shows a static map image downloaded via a third party service's static maps API. * Shows a static map image downloaded via a third party service's static maps API.
@@ -128,32 +134,46 @@ private fun BoxWithConstraintsScope.LoadableMapContent(
var retryHash by remember { mutableIntStateOf(0) } var retryHash by remember { mutableIntStateOf(0) }
val builder = remember { StaticMapUrlBuilder() } val builder = remember { StaticMapUrlBuilder() }
val painter = rememberAsyncImagePainter( val (painter, state, contentScale) = if (LocalInspectionMode.current) {
model = if (constraints.isZero) { val painter = painterResource(CommonDrawables.sample_map)
// Avoid building a URL if any of the size constraints is zero val state = AsyncImagePainter.State.Success(
null painter = painter,
} else { result = SuccessResult(
ImageRequest.Builder(context) image = createBitmap(1, 1, Bitmap.Config.ALPHA_8).asImage(),
.data( request = ImageRequest.Builder(context).build()
builder.build( )
lat = location.lat, )
lon = location.lon, Triple(painter, state, ContentScale.Crop)
zoom = zoom, } else {
darkMode = darkMode, val painter = rememberAsyncImagePainter(
width = constraints.maxWidth, model = if (constraints.isZero) {
height = constraints.maxHeight, // Avoid building a URL if any of the size constraints is zero
density = LocalDensity.current.density, null
} else {
ImageRequest.Builder(context)
.data(
builder.build(
lat = location.lat,
lon = location.lon,
zoom = zoom,
darkMode = darkMode,
width = constraints.maxWidth,
height = constraints.maxHeight,
density = LocalDensity.current.density,
)
) )
) .size(width = constraints.maxWidth, height = constraints.maxHeight)
.size(width = constraints.maxWidth, height = constraints.maxHeight) .apply {
.apply { extras.set(Extras.Key("retry_hash"), retryHash).build()
extras.set(Extras.Key("retry_hash"), retryHash).build() }
} .build()
.build() }
} )
)
val state by painter.state.collectAsState()
Triple(painter, state, ContentScale.Fit)
}
val state by painter.state.collectAsState()
when (state) { when (state) {
is AsyncImagePainter.State.Success -> { is AsyncImagePainter.State.Success -> {
Image( Image(
@@ -162,7 +182,7 @@ private fun BoxWithConstraintsScope.LoadableMapContent(
modifier = Modifier.size(width = maxWidth, height = maxHeight), modifier = Modifier.size(width = maxWidth, height = maxHeight),
// The returned image can be smaller than the requested size due to the static maps API having // The returned image can be smaller than the requested size due to the static maps API having
// a max width and height of 2048 px. We apply ContentScale.Fit to handle this. // a max width and height of 2048 px. We apply ContentScale.Fit to handle this.
contentScale = ContentScale.Fit, contentScale = contentScale,
) )
LocationPin(variant = pinVariant, modifier = Modifier.centerBottomEdge(this)) LocationPin(variant = pinVariant, modifier = Modifier.centerBottomEdge(this))
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 KiB