fix(ios): gif causing glithces in liquid glass bar

This commit is contained in:
tapframe 2026-05-09 00:28:06 +05:30
parent 7290158c53
commit d342959493
3 changed files with 42 additions and 4 deletions

View file

@ -70,6 +70,7 @@ import org.jetbrains.compose.resources.stringResource
@Composable @Composable
fun HomeScreen( fun HomeScreen(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
animateCollectionGifs: Boolean = true,
onCatalogClick: ((HomeCatalogSection) -> Unit)? = null, onCatalogClick: ((HomeCatalogSection) -> Unit)? = null,
onPosterClick: ((MetaPreview) -> Unit)? = null, onPosterClick: ((MetaPreview) -> Unit)? = null,
onPosterLongClick: ((MetaPreview) -> Unit)? = null, onPosterLongClick: ((MetaPreview) -> Unit)? = null,
@ -560,6 +561,7 @@ fun HomeScreen(
collection = collection, collection = collection,
modifier = Modifier.padding(bottom = 12.dp), modifier = Modifier.padding(bottom = 12.dp),
sectionPadding = homeSectionPadding, sectionPadding = homeSectionPadding,
animateGifs = animateCollectionGifs,
onFolderClick = onFolderClick, onFolderClick = onFolderClick,
) )
} }

View file

@ -37,6 +37,7 @@ fun HomeCollectionRowSection(
collection: Collection, collection: Collection,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
sectionPadding: Dp? = null, sectionPadding: Dp? = null,
animateGifs: Boolean = true,
onFolderClick: ((collectionId: String, folderId: String) -> Unit)? = null, onFolderClick: ((collectionId: String, folderId: String) -> Unit)? = null,
) { ) {
if (collection.folders.isEmpty()) return if (collection.folders.isEmpty()) return
@ -46,6 +47,7 @@ fun HomeCollectionRowSection(
collection = collection, collection = collection,
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
sectionPadding = sectionPadding, sectionPadding = sectionPadding,
animateGifs = animateGifs,
onFolderClick = onFolderClick, onFolderClick = onFolderClick,
) )
} else { } else {
@ -54,6 +56,7 @@ fun HomeCollectionRowSection(
collection = collection, collection = collection,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
sectionPadding = homeSectionHorizontalPaddingForWidth(maxWidth.value), sectionPadding = homeSectionHorizontalPaddingForWidth(maxWidth.value),
animateGifs = animateGifs,
onFolderClick = onFolderClick, onFolderClick = onFolderClick,
) )
} }
@ -65,6 +68,7 @@ private fun HomeCollectionRowSectionContent(
collection: Collection, collection: Collection,
modifier: Modifier, modifier: Modifier,
sectionPadding: Dp, sectionPadding: Dp,
animateGifs: Boolean,
onFolderClick: ((collectionId: String, folderId: String) -> Unit)?, onFolderClick: ((collectionId: String, folderId: String) -> Unit)?,
) { ) {
NuvioShelfSection( NuvioShelfSection(
@ -77,6 +81,7 @@ private fun HomeCollectionRowSectionContent(
) { folder -> ) { folder ->
CollectionFolderCard( CollectionFolderCard(
folder = folder, folder = folder,
animateGifs = animateGifs,
onClick = onFolderClick?.let { { it(collection.id, folder.id) } }, onClick = onFolderClick?.let { { it(collection.id, folder.id) } },
) )
} }
@ -86,6 +91,7 @@ private fun HomeCollectionRowSectionContent(
private fun CollectionFolderCard( private fun CollectionFolderCard(
folder: CollectionFolder, folder: CollectionFolder,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
animateGifs: Boolean = true,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
) { ) {
val posterCardStyle = rememberPosterCardStyleUiState() val posterCardStyle = rememberPosterCardStyleUiState()
@ -138,7 +144,7 @@ private fun CollectionFolderCard(
contentDescription = folder.title, contentDescription = folder.title,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
animateIfPossible = isAnimatedCollectionFolderImage(folder, imageUrl), animateIfPossible = animateGifs && isAnimatedCollectionFolderImage(folder, imageUrl),
) )
} }
!folder.coverEmoji.isNullOrBlank() -> { !folder.coverEmoji.isNullOrBlank() -> {

View file

@ -2,6 +2,7 @@ package com.nuvio.app.features.home.components
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
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
@ -51,6 +52,16 @@ private data class ExpandedGifFrames(
val tickCentiseconds: Int, val tickCentiseconds: Int,
) )
private class GifImageViewHolder {
var imageView: UIImageView? = null
fun clear() {
imageView?.stopAnimating()
imageView?.image = null
imageView = null
}
}
@OptIn(ExperimentalForeignApi::class) @OptIn(ExperimentalForeignApi::class)
@Composable @Composable
internal actual fun CollectionCardRemoteImage( internal actual fun CollectionCardRemoteImage(
@ -76,6 +87,13 @@ internal actual fun CollectionCardRemoteImage(
gifImage = loadGifImage(imageUrl) gifImage = loadGifImage(imageUrl)
} }
val imageViewHolder = remember(imageUrl) { GifImageViewHolder() }
DisposableEffect(imageUrl) {
onDispose {
imageViewHolder.clear()
}
}
UIKitView( UIKitView(
modifier = modifier, modifier = modifier,
factory = { factory = {
@ -83,19 +101,31 @@ internal actual fun CollectionCardRemoteImage(
contentMode = UIViewContentMode.UIViewContentModeScaleAspectFill contentMode = UIViewContentMode.UIViewContentModeScaleAspectFill
clipsToBounds = true clipsToBounds = true
userInteractionEnabled = false userInteractionEnabled = false
image = gifImage
tag = imageUrl.hashCode().toLong() tag = imageUrl.hashCode().toLong()
imageViewHolder.imageView = this
updateGifImage(gifImage)
} }
}, },
update = { imageView -> update = { imageView ->
imageViewHolder.imageView = imageView
if (imageView.tag != imageUrl.hashCode().toLong()) { if (imageView.tag != imageUrl.hashCode().toLong()) {
imageView.tag = imageUrl.hashCode().toLong() imageView.tag = imageUrl.hashCode().toLong()
} }
imageView.image = gifImage imageView.updateGifImage(gifImage)
}, },
) )
} }
private fun UIImageView.updateGifImage(image: UIImage?) {
if (this.image != image) {
stopAnimating()
this.image = image
}
if (image != null) {
startAnimating()
}
}
private fun cachedGifImage(imageUrl: String): UIImage? { private fun cachedGifImage(imageUrl: String): UIImage? {
val image = gifImageCache[imageUrl] ?: return null val image = gifImageCache[imageUrl] ?: return null
gifImageCacheOrder.remove(imageUrl) gifImageCacheOrder.remove(imageUrl)