Workaround to not invalidate shared element modifier chain (#1944)
* Try to fix SET * Drop check --------- Co-authored-by: Dude so hot <djohn@fbi.gov>
This commit is contained in:
1 parent
900da46090
commit
7dd87c1ff6
3 files changed
+50
-55
No files matched your search
@@ -14,10 +14,8 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
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 as CoilImage
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.compose.ConstraintsSizeResolver
|
||||
@@ -27,8 +25,8 @@ import coil3.request.ImageRequest
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.ktbuilder.imageRequest
|
||||
import com.hippo.ehviewer.ui.tools.SETNodeGenerator
|
||||
import com.hippo.ehviewer.ui.tools.SharedElementBox
|
||||
import com.hippo.ehviewer.ui.tools.TransitionsVisibilityScope
|
||||
import com.hippo.ehviewer.ui.tools.sharedBounds
|
||||
import com.hippo.ehviewer.ui.tools.shouldCrop
|
||||
import com.hippo.ehviewer.ui.tools.thenIf
|
||||
|
||||
@@ -57,35 +55,17 @@ fun Modifier.imageRequest(request: ImageRequest): Modifier {
|
||||
}
|
||||
}
|
||||
|
||||
context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
fun EhAsyncThumb(
|
||||
model: GalleryInfo,
|
||||
modifier: Modifier = Modifier,
|
||||
onSuccess: ((CoilImage) -> Unit)? = null,
|
||||
contentScale: ContentScale = ContentScale.Fit,
|
||||
) = AsyncImage(
|
||||
model = requestOf(model),
|
||||
contentDescription = null,
|
||||
modifier = modifier.sharedBounds(key = "${model.gid}").clip(ShapeDefaults.Medium),
|
||||
onSuccess = onSuccess?.let { callback ->
|
||||
{ callback(it.result.image) }
|
||||
},
|
||||
contentScale = contentScale,
|
||||
)
|
||||
|
||||
context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
|
||||
@Composable
|
||||
fun EhAsyncCropThumb(
|
||||
key: GalleryInfo,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
) = SharedElementBox(key = "${key.gid}", shape = ShapeDefaults.Medium) {
|
||||
var contentScale by remember(key) { mutableStateOf(ContentScale.Fit) }
|
||||
AsyncImage(
|
||||
model = requestOf(key),
|
||||
contentDescription = null,
|
||||
modifier = modifier.sharedBounds(key = "${key.gid}").clip(ShapeDefaults.Medium),
|
||||
modifier = modifier,
|
||||
onSuccess = {
|
||||
if (it.result.image.shouldCrop) {
|
||||
contentScale = ContentScale.Crop
|
||||
@@ -100,28 +80,26 @@ context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
|
||||
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
|
||||
}
|
||||
},
|
||||
)
|
||||
val state by painter.state.collectAsState()
|
||||
Card(modifier = modifier) {
|
||||
) = Card(modifier = modifier) {
|
||||
SharedElementBox(key = "${key.gid}", shape = ShapeDefaults.Medium) {
|
||||
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
|
||||
}
|
||||
},
|
||||
)
|
||||
val state by painter.state.collectAsState()
|
||||
Image(
|
||||
painter = painter,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.thenIf(state !is AsyncImagePainter.State.Success) {
|
||||
// Keep applying this when state is `Loading` to avoid cutting off the ripple
|
||||
clickable {
|
||||
if (state is AsyncImagePainter.State.Error) painter.restart()
|
||||
}
|
||||
}.imageRequest(request).fillMaxSize().sharedBounds(key = "${key.gid}").clip(ShapeDefaults.Medium),
|
||||
clickable { if (state is AsyncImagePainter.State.Error) painter.restart() }
|
||||
}.imageRequest(request).fillMaxSize(),
|
||||
contentScale = contentScale,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import arrow.core.Tuple7
|
||||
import coil3.compose.AsyncImage
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
@@ -51,6 +52,7 @@ import com.hippo.ehviewer.download.DownloadManager
|
||||
import com.hippo.ehviewer.ui.tools.CrystalCard
|
||||
import com.hippo.ehviewer.ui.tools.ElevatedCard
|
||||
import com.hippo.ehviewer.ui.tools.GalleryListCardRating
|
||||
import com.hippo.ehviewer.ui.tools.SharedElementBox
|
||||
import com.hippo.ehviewer.ui.tools.TransitionsVisibilityScope
|
||||
import com.hippo.ehviewer.ui.tools.listThumbGenerator
|
||||
import com.hippo.ehviewer.util.FavouriteStatusRouter
|
||||
@@ -219,22 +221,25 @@ fun GalleryInfoGridItem(
|
||||
interactionSource = interactionSource,
|
||||
) {
|
||||
Box {
|
||||
var ratio by remember(info) {
|
||||
val ratio = if (info.thumbHeight != 0) {
|
||||
(info.thumbWidth.toFloat() / info.thumbHeight).coerceIn(MIN_RATIO, MAX_RATIO)
|
||||
} else {
|
||||
DEFAULT_RATIO
|
||||
}
|
||||
mutableFloatStateOf(ratio)
|
||||
}
|
||||
with(listThumbGenerator) {
|
||||
EhAsyncThumb(
|
||||
model = info,
|
||||
modifier = Modifier.aspectRatio(ratio),
|
||||
onSuccess = {
|
||||
ratio = (it.width.toFloat() / it.height).coerceIn(MIN_RATIO, MAX_RATIO)
|
||||
},
|
||||
)
|
||||
SharedElementBox(key = "${info.gid}", shape = ShapeDefaults.Medium) {
|
||||
var ratio by remember(info) {
|
||||
val ratio = if (info.thumbHeight != 0) {
|
||||
(info.thumbWidth.toFloat() / info.thumbHeight).coerceIn(MIN_RATIO, MAX_RATIO)
|
||||
} else {
|
||||
DEFAULT_RATIO
|
||||
}
|
||||
mutableFloatStateOf(ratio)
|
||||
}
|
||||
AsyncImage(
|
||||
model = requestOf(info),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.aspectRatio(ratio),
|
||||
onSuccess = {
|
||||
ratio = (it.result.image.width.toFloat() / it.result.image.height).coerceIn(MIN_RATIO, MAX_RATIO)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
val categoryColor = EhUtils.getCategoryColor(info.category)
|
||||
Badge(
|
||||
|
||||
@@ -6,11 +6,16 @@ import androidx.compose.animation.ExitTransition
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
val NoopTransitionsVisibilityScope = TransitionsVisibilityScope(emptySet())
|
||||
@@ -45,6 +50,13 @@ fun Modifier.sharedBounds(
|
||||
}
|
||||
}
|
||||
|
||||
context(SharedTransitionScope, TransitionsVisibilityScope, SETNodeGenerator)
|
||||
@Composable
|
||||
inline fun SharedElementBox(key: String, shape: Shape, crossinline content: @Composable BoxScope.() -> Unit) {
|
||||
val modifier = Modifier.sharedBounds(key = key).clip(shape)
|
||||
CompositionLocalProvider { Box(modifier = modifier, content = content) }
|
||||
}
|
||||
|
||||
data class SETNode(
|
||||
val contentKey: String,
|
||||
val uniqueID: String,
|
||||
|
||||
Reference in new issue
Block a user