mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 15:32:01 +00:00
fix(ios): gif causing glithces in liquid glass bar
This commit is contained in:
parent
7290158c53
commit
d342959493
3 changed files with 42 additions and 4 deletions
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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() -> {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -311,4 +341,4 @@ private fun ByteArray.readUnsignedShort(startIndex: Int): Int {
|
||||||
return this[startIndex].unsignedInt() or (this[startIndex + 1].unsignedInt() shl 8)
|
return this[startIndex].unsignedInt() or (this[startIndex + 1].unsignedInt() shl 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Byte.unsignedInt(): Int = toInt() and 0xFF
|
private fun Byte.unsignedInt(): Int = toInt() and 0xFF
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue