fix(feeds): clip + preload content warning on cropped grid cells
- Pass contentScale through to ContentWarningOverBlurhash so grid cells (ContentScale.Crop) use fillMaxSize instead of forcing the image's native aspect ratio, keeping the blurhash and overlay within the cell. - Clip the overlay to its bounds to stop the icon/button from drawing over neighboring cells or other components. - Preload the image through Coil while the warning is visible so the image is cached by the time the user taps "Show anyway".
This commit is contained in:
+24
-6
@@ -40,20 +40,25 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import coil3.imageLoader
|
||||||
|
import coil3.request.ImageRequest
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
@@ -112,6 +117,8 @@ fun SensitivityWarningOverBlurhash(
|
|||||||
blurhash: String?,
|
blurhash: String?,
|
||||||
ratio: Float?,
|
ratio: Float?,
|
||||||
description: String?,
|
description: String?,
|
||||||
|
contentScale: ContentScale,
|
||||||
|
preloadUrl: String?,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -124,10 +131,19 @@ fun SensitivityWarningOverBlurhash(
|
|||||||
|
|
||||||
var showContentWarningNote by remember(accountState) { mutableStateOf(accountState.value != true) }
|
var showContentWarningNote by remember(accountState) { mutableStateOf(accountState.value != true) }
|
||||||
|
|
||||||
|
if (showContentWarningNote && preloadUrl != null) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
LaunchedEffect(preloadUrl) {
|
||||||
|
runCatching {
|
||||||
|
context.imageLoader.enqueue(ImageRequest.Builder(context).data(preloadUrl).build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CrossfadeIfEnabled(targetState = showContentWarningNote, accountViewModel = accountViewModel) {
|
CrossfadeIfEnabled(targetState = showContentWarningNote, accountViewModel = accountViewModel) {
|
||||||
if (it) {
|
if (it) {
|
||||||
if (blurhash != null) {
|
if (blurhash != null) {
|
||||||
ContentWarningOverBlurhash(reason, blurhash, ratio, description) { showContentWarningNote = false }
|
ContentWarningOverBlurhash(reason, blurhash, ratio, description, contentScale) { showContentWarningNote = false }
|
||||||
} else {
|
} else {
|
||||||
ContentWarningNote(reason) { showContentWarningNote = false }
|
ContentWarningNote(reason) { showContentWarningNote = false }
|
||||||
}
|
}
|
||||||
@@ -189,6 +205,7 @@ fun ContentWarningOverBlurhashPreview() {
|
|||||||
blurhash = "LEHV6nWB2yk8pyo0adR*.7kCMdnj",
|
blurhash = "LEHV6nWB2yk8pyo0adR*.7kCMdnj",
|
||||||
ratio = 16f / 9f,
|
ratio = 16f / 9f,
|
||||||
description = null,
|
description = null,
|
||||||
|
contentScale = ContentScale.FillWidth,
|
||||||
onDismiss = {},
|
onDismiss = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -200,16 +217,17 @@ fun ContentWarningOverBlurhash(
|
|||||||
blurhash: String,
|
blurhash: String,
|
||||||
ratio: Float?,
|
ratio: Float?,
|
||||||
description: String?,
|
description: String?,
|
||||||
|
contentScale: ContentScale,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val sizingModifier =
|
val sizingModifier =
|
||||||
if (ratio != null) {
|
when {
|
||||||
Modifier.fillMaxWidth().aspectRatio(ratio)
|
contentScale == ContentScale.Crop -> Modifier.fillMaxSize()
|
||||||
} else {
|
ratio != null -> Modifier.fillMaxWidth().aspectRatio(ratio)
|
||||||
Modifier.fillMaxWidth()
|
else -> Modifier.fillMaxWidth()
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(modifier = sizingModifier) {
|
Box(modifier = sizingModifier.clipToBounds()) {
|
||||||
DisplayBlurHash(
|
DisplayBlurHash(
|
||||||
blurhash = blurhash,
|
blurhash = blurhash,
|
||||||
description = description,
|
description = description,
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ fun ZoomableContentView(
|
|||||||
blurhash = content.blurhash,
|
blurhash = content.blurhash,
|
||||||
ratio = ratio,
|
ratio = ratio,
|
||||||
description = content.description,
|
description = content.description,
|
||||||
|
contentScale = contentScale,
|
||||||
|
preloadUrl = content.url,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
) {
|
) {
|
||||||
TwoSecondController(content) { controllerVisible ->
|
TwoSecondController(content) { controllerVisible ->
|
||||||
@@ -179,6 +181,8 @@ fun ZoomableContentView(
|
|||||||
blurhash = content.blurhash,
|
blurhash = content.blurhash,
|
||||||
ratio = ratio,
|
ratio = ratio,
|
||||||
description = content.description,
|
description = content.description,
|
||||||
|
contentScale = contentScale,
|
||||||
|
preloadUrl = null,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
|
|||||||
Reference in New Issue
Block a user