Implement retry on click for thumbnails

This commit is contained in:
FooIbar committed 2024-11-09 11:27:10 +08:00
1 parent 85b03d9d8a
commit 4052007de8
4 files changed
+108 -39

No files matched your search

@@ -1,6 +1,9 @@
package com.hippo.ehviewer.ui.main
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Card
import androidx.compose.material3.ShapeDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.NonRestartableComposable
@@ -12,8 +15,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import coil3.Image
import coil3.Image as CoilImage
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import coil3.compose.ConstraintsSizeResolver
import coil3.compose.rememberAsyncImagePainter
import coil3.compose.rememberConstraintsSizeResolver
import coil3.request.ImageRequest
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.ktbuilder.imageRequest
@@ -25,7 +32,25 @@ import com.hippo.ehviewer.ui.tools.shouldCrop
@NonRestartableComposable
fun requestOf(model: GalleryInfo): ImageRequest {
val context = LocalContext.current
return remember(model) { context.imageRequest(model) }
return remember(model) { context.imageRequest(model) }.withSizeResolver()
}
@Composable
@NonRestartableComposable
fun ImageRequest.withSizeResolver() = if (defined.sizeResolver != null) {
this
} else {
val sizeResolver = rememberConstraintsSizeResolver()
remember(this, sizeResolver) { newBuilder().size(sizeResolver).build() }
}
fun Modifier.imageRequest(request: ImageRequest): Modifier {
val sizeResolver = request.sizeResolver
return if (sizeResolver is ConstraintsSizeResolver) {
then(sizeResolver)
} else {
this
}
}
context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
@@ -34,7 +59,7 @@ context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
fun EhAsyncThumb(
model: GalleryInfo,
modifier: Modifier = Modifier,
onSuccess: ((Image) -> Unit)? = null,
onSuccess: ((CoilImage) -> Unit)? = null,
contentScale: ContentScale = ContentScale.Fit,
) = AsyncImage(
model = requestOf(model),
@@ -69,3 +94,35 @@ fun EhAsyncCropThumb(
contentScale = contentScale,
)
}
@Composable
fun EhThumbCard(
key: GalleryInfo,
modifier: Modifier = Modifier,
) {
var contentScale by remember(key) { mutableStateOf(ContentScale.Fit) }
val request = requestOf(key)
val painter = rememberAsyncImagePainter(
model = request,
onSuccess = {
if (it.result.image.shouldCrop) {
contentScale = ContentScale.Crop
}
},
)
Card(
onClick = {
if (painter.state.value is AsyncImagePainter.State.Error) {
painter.restart()
}
},
modifier = modifier,
) {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.imageRequest(request).fillMaxSize().clip(ShapeDefaults.Medium),
contentScale = contentScale,
)
}
}
@@ -109,16 +109,14 @@ fun GalleryDetailHeaderCard(
modifier: Modifier = Modifier,
) = ElevatedCard(modifier = modifier) {
Row {
Card {
with(detailThumbGenerator) {
EhAsyncCropThumb(
key = remember(info.gid) { info },
modifier = Modifier.size(
dimensionResource(id = R.dimen.gallery_detail_thumb_width),
dimensionResource(id = R.dimen.gallery_detail_thumb_height),
),
)
}
with(detailThumbGenerator) {
EhThumbCard(
key = remember(info.gid) { info },
modifier = Modifier.size(
dimensionResource(id = R.dimen.gallery_detail_thumb_width),
dimensionResource(id = R.dimen.gallery_detail_thumb_height),
),
)
}
Spacer(modifier = Modifier.weight(0.5F))
Column(
@@ -18,7 +18,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Badge
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
@@ -108,13 +107,11 @@ fun GalleryInfoListItem(
interactionSource = interactionSource,
) {
Row {
Card {
with(listThumbGenerator) {
EhAsyncCropThumb(
key = info,
modifier = Modifier.aspectRatio(DEFAULT_RATIO).fillMaxSize(),
)
}
with(listThumbGenerator) {
EhThumbCard(
key = info,
modifier = Modifier.aspectRatio(DEFAULT_RATIO),
)
}
ConstraintLayout(
modifier = Modifier.padding(start = 8.dp, top = 2.dp, end = 4.dp, bottom = 4.dp).fillMaxSize(),
@@ -1,5 +1,6 @@
package com.hippo.ehviewer.ui.main
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
@@ -20,8 +21,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import coil3.BitmapImage
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter.State
import coil3.compose.rememberAsyncImagePainter
import coil3.request.ImageRequest
import com.hippo.ehviewer.client.data.GalleryPreview
import com.hippo.ehviewer.client.data.V2GalleryPreview
@@ -33,19 +34,19 @@ import com.hippo.ehviewer.ui.tools.shouldCrop
@NonRestartableComposable
fun requestOf(model: GalleryPreview): ImageRequest {
val context = LocalContext.current
return remember(model) { context.imageRequest(model) }
return remember(model) { context.imageRequest(model) }.withSizeResolver()
}
@Composable
fun EhAsyncPreview(
fun EhPreviewCard(
model: GalleryPreview,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
var contentScale by remember(model) { mutableStateOf(ContentScale.Fit) }
AsyncImage(
model = requestOf(model),
contentDescription = null,
modifier = modifier,
val request = requestOf(model)
val painter = rememberAsyncImagePainter(
model = request,
transform = {
if (it is State.Success && model is V2GalleryPreview) {
with(model) {
@@ -74,8 +75,23 @@ fun EhAsyncPreview(
}
}
},
contentScale = contentScale,
)
CrystalCard(
onClick = onClick,
onLongClick = {
if (painter.state.value is State.Error) {
painter.restart()
}
},
modifier = modifier,
) {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.imageRequest(request).fillMaxSize(),
contentScale = contentScale,
)
}
}
@Composable
@@ -86,16 +102,17 @@ fun EhPreviewItem(
onClick: () -> Unit,
) = Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(contentAlignment = Alignment.Center) {
CrystalCard(
onClick = onClick,
modifier = Modifier.aspectRatio(DEFAULT_RATIO),
) {
if (galleryPreview != null) {
EhAsyncPreview(
model = galleryPreview,
modifier = Modifier.fillMaxSize(),
)
}
if (galleryPreview != null) {
EhPreviewCard(
model = galleryPreview,
onClick = onClick,
modifier = Modifier.aspectRatio(DEFAULT_RATIO),
)
} else {
CrystalCard(
onClick = onClick,
modifier = Modifier.aspectRatio(DEFAULT_RATIO),
) {}
}
}
Text(text = "${position + 1}")