prevent race condition: Added a state-aware rememberFirstImageOrientation helper so each gallery watches the cache until the first image’s real aspect ratio is known

This commit is contained in:
davotoula
2025-10-21 15:56:18 +01:00
parent c735c358bb
commit a055f473cb

View File

@@ -34,6 +34,11 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
@@ -47,6 +52,8 @@ import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.Size5dp import com.vitorpamplona.amethyst.ui.theme.Size5dp
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
private const val ASPECT_RATIO = 4f / 3f private const val ASPECT_RATIO = 4f / 3f
private const val PORTRAIT_ASPECT_RATIO = 3f / 4f private const val PORTRAIT_ASPECT_RATIO = 3f / 4f
@@ -81,6 +88,32 @@ private fun MediaUrlImage?.resolveOrientation(
) )
} }
@Composable
private fun rememberFirstImageOrientation(firstImage: MediaUrlImage?): FirstImageOrientation {
val initialOrientation =
remember(firstImage) {
firstImage.resolveOrientation(ASPECT_RATIO, PORTRAIT_ASPECT_RATIO)
}
var orientation by remember(firstImage) { mutableStateOf(initialOrientation) }
LaunchedEffect(firstImage) {
if (firstImage == null) return@LaunchedEffect
if (firstImage.dim?.hasSize() == true) return@LaunchedEffect
while (isActive) {
val ratio = firstImage.resolvedAspectRatio()
if (ratio != null && ratio > 0f) {
orientation = FirstImageOrientation(ratio, ratio >= 1f)
break
}
delay(200)
}
}
return orientation
}
@Composable @Composable
private fun GalleryImage( private fun GalleryImage(
image: MediaUrlImage, image: MediaUrlImage,
@@ -151,7 +184,7 @@ private fun TwoImageGallery(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
roundedCorner: Boolean, roundedCorner: Boolean,
) { ) {
val orientation = images.firstOrNull().resolveOrientation(ASPECT_RATIO, PORTRAIT_ASPECT_RATIO) val orientation = rememberFirstImageOrientation(images.firstOrNull())
if (orientation.isLandscape) { if (orientation.isLandscape) {
Column( Column(
@@ -195,7 +228,7 @@ private fun ThreeImageGallery(
roundedCorner: Boolean, roundedCorner: Boolean,
) { ) {
val firstImage = images.first() val firstImage = images.first()
val orientation = firstImage.resolveOrientation(ASPECT_RATIO, PORTRAIT_ASPECT_RATIO) val orientation = rememberFirstImageOrientation(firstImage)
val remainingImages = images.drop(1) val remainingImages = images.drop(1)
if (orientation.isLandscape) { if (orientation.isLandscape) {