mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:55:41 +00:00
Try fixing location pin previews (#6495)
* Try fixing location pin previews * Update screenshots --------- Co-authored-by: ElementBot <android@element.io> Co-authored-by: Benoit Marty <benoitm@element.io>
This commit is contained in:
committed by
GitHub
parent
bc37d3d8d9
commit
579bc7db62
+38
-19
@@ -32,9 +32,13 @@ import androidx.compose.ui.graphics.asImageBitmap
|
|||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
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.platform.LocalResources
|
||||||
import androidx.compose.ui.unit.Density
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.core.graphics.createBitmap
|
import androidx.core.graphics.createBitmap
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.core.graphics.withSave
|
import androidx.core.graphics.withSave
|
||||||
import coil3.Image
|
import coil3.Image
|
||||||
import coil3.ImageLoader
|
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.components.avatar.AvatarSize
|
||||||
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
|
||||||
|
|
||||||
private val PIN_WIDTH = 42.dp
|
private val PIN_WIDTH = 42.dp
|
||||||
private val PIN_HEIGHT = PIN_WIDTH * 1.2f
|
private val PIN_HEIGHT = PIN_WIDTH * 1.2f
|
||||||
@@ -99,21 +104,33 @@ fun LocationPin(
|
|||||||
fun rememberLocationPinBitmap(variant: PinVariant): ImageBitmap? {
|
fun rememberLocationPinBitmap(variant: PinVariant): ImageBitmap? {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val imageLoader = SingletonImageLoader.get(context)
|
|
||||||
val colors = pinColors(variant)
|
val colors = pinColors(variant)
|
||||||
val cacheKey = rememberCacheKey(variant)
|
val cacheKey = rememberCacheKey(variant)
|
||||||
return produceState<ImageBitmap?>(initialValue = null, cacheKey) {
|
val resources = LocalResources.current
|
||||||
val memoryCacheKey = MemoryCache.Key(cacheKey)
|
|
||||||
val cached = imageLoader.memoryCache?.get(memoryCacheKey)
|
return if (LocalInspectionMode.current) {
|
||||||
if (cached != null) {
|
// In preview mode, skip async loading and return a simple placeholder image instead to avoid using ImageLoader
|
||||||
value = cached.image.toBitmap().asImageBitmap()
|
val dimensions = PinDimensions(density)
|
||||||
} else {
|
val avatarImage = ResourcesCompat.getDrawable(resources, CommonDrawables.sample_avatar, context.theme)?.toBitmap()?.asImage()
|
||||||
val dimensions = PinDimensions(density)
|
LocationPinRenderer.renderPin(variant, colors, dimensions, avatarImage).asImageBitmap()
|
||||||
val bitmap = LocationPinRenderer.renderPin(variant, colors, dimensions, context, imageLoader)
|
} else {
|
||||||
imageLoader.memoryCache?.set(memoryCacheKey, MemoryCache.Value(bitmap.asImage()))
|
produceState<ImageBitmap?>(initialValue = null, cacheKey) {
|
||||||
value = bitmap.asImageBitmap()
|
val imageLoader = SingletonImageLoader.get(context)
|
||||||
}
|
val memoryCacheKey = MemoryCache.Key(cacheKey)
|
||||||
}.value
|
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
|
@Composable
|
||||||
@@ -208,19 +225,17 @@ private object LocationPinRenderer {
|
|||||||
/**
|
/**
|
||||||
* Renders a pin variant to bitmap. Suspending for async avatar loading.
|
* Renders a pin variant to bitmap. Suspending for async avatar loading.
|
||||||
*/
|
*/
|
||||||
suspend fun renderPin(
|
fun renderPin(
|
||||||
variant: PinVariant,
|
variant: PinVariant,
|
||||||
colors: PinColors,
|
colors: PinColors,
|
||||||
dimensions: PinDimensions,
|
dimensions: PinDimensions,
|
||||||
context: Context,
|
avatarImage: Image?,
|
||||||
imageLoader: ImageLoader,
|
|
||||||
): Bitmap {
|
): Bitmap {
|
||||||
val bitmap = createBitmap(dimensions.pinWidth.toInt(), dimensions.pinHeight.toInt())
|
val bitmap = createBitmap(dimensions.pinWidth.toInt(), dimensions.pinHeight.toInt())
|
||||||
val canvas = Canvas(bitmap)
|
val canvas = Canvas(bitmap)
|
||||||
canvas.drawPinShape(colors.fill, colors.stroke, dimensions)
|
canvas.drawPinShape(colors.fill, colors.stroke, dimensions)
|
||||||
when (variant) {
|
when (variant) {
|
||||||
is PinVariant.UserLocation -> {
|
is PinVariant.UserLocation -> {
|
||||||
val avatarImage = loadAvatarImage(variant.avatarData, context, imageLoader)
|
|
||||||
canvas.drawAvatar(
|
canvas.drawAvatar(
|
||||||
avatarImage = avatarImage,
|
avatarImage = avatarImage,
|
||||||
avatarData = variant.avatarData,
|
avatarData = variant.avatarData,
|
||||||
@@ -284,11 +299,15 @@ private object LocationPinRenderer {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadAvatarImage(
|
suspend fun loadAvatarImage(
|
||||||
avatarData: AvatarData,
|
variant: PinVariant,
|
||||||
context: Context,
|
context: Context,
|
||||||
imageLoader: ImageLoader,
|
imageLoader: ImageLoader,
|
||||||
): Image? {
|
): Image? {
|
||||||
|
val avatarData = when (variant) {
|
||||||
|
is PinVariant.UserLocation -> variant.avatarData
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
val request = ImageRequest.Builder(context)
|
val request = ImageRequest.Builder(context)
|
||||||
.data(avatarData)
|
.data(avatarData)
|
||||||
// Disable hardware rendering for Canvas
|
// Disable hardware rendering for Canvas
|
||||||
|
|||||||
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png
LFS
BIN
Binary file not shown.
Reference in New Issue
Block a user