mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-03 08:49:07 +00:00
fix: using unique key for transition
This commit is contained in:
parent
81af639fe9
commit
fa7e3aabfc
5 changed files with 38 additions and 15 deletions
|
|
@ -171,6 +171,7 @@ data class PersonDetailRoute(
|
|||
val personId: Int,
|
||||
val personName: String,
|
||||
val personPhoto: String? = null,
|
||||
val castAvatarTransitionKey: String? = null,
|
||||
val preferCrew: Boolean = false,
|
||||
)
|
||||
|
||||
|
|
@ -766,7 +767,7 @@ private fun MainAppContent(
|
|||
)
|
||||
}
|
||||
},
|
||||
onCastClick = { person ->
|
||||
onCastClick = { person, avatarTransitionKey ->
|
||||
val tmdbId = person.tmdbId
|
||||
if (tmdbId != null && tmdbId > 0) {
|
||||
navController.navigate(
|
||||
|
|
@ -774,6 +775,7 @@ private fun MainAppContent(
|
|||
personId = tmdbId,
|
||||
personName = person.name,
|
||||
personPhoto = person.photo,
|
||||
castAvatarTransitionKey = avatarTransitionKey,
|
||||
preferCrew = person.role?.let {
|
||||
it.equals("Director", ignoreCase = true) ||
|
||||
it.equals("Writer", ignoreCase = true) ||
|
||||
|
|
@ -807,6 +809,7 @@ private fun MainAppContent(
|
|||
personId = route.personId,
|
||||
personName = route.personName,
|
||||
initialProfilePhoto = route.personPhoto,
|
||||
avatarTransitionKey = route.castAvatarTransitionKey,
|
||||
preferCrew = route.preferCrew,
|
||||
onBack = { navController.popBackStack() },
|
||||
onOpenMeta = { preview ->
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
package com.nuvio.app.features.details
|
||||
|
||||
internal fun castAvatarSharedTransitionKey(personId: Int): String = "cast-avatar:$personId"
|
||||
internal fun castAvatarSharedTransitionKey(
|
||||
personId: Int,
|
||||
occurrenceIndex: Int? = null,
|
||||
): String =
|
||||
if (occurrenceIndex != null) {
|
||||
"cast-avatar:$personId:$occurrenceIndex"
|
||||
} else {
|
||||
"cast-avatar:$personId"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ fun MetaDetailsScreen(
|
|||
onPlay: ((type: String, videoId: String, parentMetaId: String, parentMetaType: String, title: String, logo: String?, poster: String?, background: String?, seasonNumber: Int?, episodeNumber: Int?, episodeTitle: String?, episodeThumbnail: String?, pauseDescription: String?, resumePositionMs: Long?) -> Unit)? = null,
|
||||
onPlayManually: ((type: String, videoId: String, parentMetaId: String, parentMetaType: String, title: String, logo: String?, poster: String?, background: String?, seasonNumber: Int?, episodeNumber: Int?, episodeTitle: String?, episodeThumbnail: String?, pauseDescription: String?, resumePositionMs: Long?) -> Unit)? = null,
|
||||
onOpenMeta: ((MetaPreview) -> Unit)? = null,
|
||||
onCastClick: ((MetaPerson) -> Unit)? = null,
|
||||
onCastClick: ((MetaPerson, String?) -> Unit)? = null,
|
||||
onCompanyClick: ((MetaCompany, String) -> Unit)? = null,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
|
|
@ -919,7 +919,7 @@ private fun ConfiguredMetaSections(
|
|||
onEpisodeClick: (MetaVideo) -> Unit,
|
||||
onEpisodeLongPress: (MetaVideo) -> Unit,
|
||||
onOpenMeta: ((MetaPreview) -> Unit)?,
|
||||
onCastClick: ((MetaPerson) -> Unit)?,
|
||||
onCastClick: ((MetaPerson, String?) -> Unit)?,
|
||||
onCompanyClick: ((MetaCompany, String) -> Unit)?,
|
||||
sharedTransitionScope: SharedTransitionScope?,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope?,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ fun PersonDetailScreen(
|
|||
personId: Int,
|
||||
personName: String,
|
||||
initialProfilePhoto: String? = null,
|
||||
avatarTransitionKey: String? = null,
|
||||
preferCrew: Boolean = false,
|
||||
onBack: () -> Unit,
|
||||
onOpenMeta: (MetaPreview) -> Unit,
|
||||
|
|
@ -81,6 +82,7 @@ fun PersonDetailScreen(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var uiState by remember(personId) { mutableStateOf<PersonDetailUiState>(PersonDetailUiState.Loading) }
|
||||
val resolvedAvatarTransitionKey = avatarTransitionKey ?: castAvatarSharedTransitionKey(personId)
|
||||
|
||||
LaunchedEffect(personId) {
|
||||
uiState = PersonDetailUiState.Loading
|
||||
|
|
@ -105,6 +107,7 @@ fun PersonDetailScreen(
|
|||
personId = personId,
|
||||
personName = personName,
|
||||
profilePhoto = initialProfilePhoto,
|
||||
avatarTransitionKey = resolvedAvatarTransitionKey,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
@ -119,6 +122,7 @@ fun PersonDetailScreen(
|
|||
person = state.personDetail,
|
||||
onOpenMeta = onOpenMeta,
|
||||
initialProfilePhoto = initialProfilePhoto,
|
||||
avatarTransitionKey = resolvedAvatarTransitionKey,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
@ -147,6 +151,7 @@ private fun PersonDetailContent(
|
|||
person: PersonDetail,
|
||||
onOpenMeta: (MetaPreview) -> Unit,
|
||||
initialProfilePhoto: String? = null,
|
||||
avatarTransitionKey: String,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
) {
|
||||
|
|
@ -240,6 +245,7 @@ private fun PersonDetailContent(
|
|||
person = person,
|
||||
collapseProgress = collapseProgress,
|
||||
fallbackProfilePhoto = initialProfilePhoto,
|
||||
avatarTransitionKey = avatarTransitionKey,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
@ -292,6 +298,7 @@ private fun HeroSection(
|
|||
person: PersonDetail,
|
||||
collapseProgress: Float = 0f,
|
||||
fallbackProfilePhoto: String? = null,
|
||||
avatarTransitionKey: String,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
) {
|
||||
|
|
@ -299,7 +306,7 @@ private fun HeroSection(
|
|||
val heroScale = 1f - (collapseProgress * 0.12f)
|
||||
val heroAlpha = 1f - (collapseProgress * 0.35f)
|
||||
val avatarUrl = person.profilePhoto?.takeIf { it.isNotBlank() } ?: fallbackProfilePhoto
|
||||
val avatarCacheKey = castAvatarSharedTransitionKey(person.tmdbId)
|
||||
val avatarCacheKey = avatarTransitionKey
|
||||
val platformContext = LocalPlatformContext.current
|
||||
val avatarRequest = if (!avatarUrl.isNullOrBlank()) {
|
||||
remember(platformContext, avatarUrl, avatarCacheKey) {
|
||||
|
|
@ -317,7 +324,7 @@ private fun HeroSection(
|
|||
with(sharedTransitionScope) {
|
||||
Modifier.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(
|
||||
key = castAvatarSharedTransitionKey(person.tmdbId),
|
||||
key = avatarTransitionKey,
|
||||
),
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
@ -434,11 +441,12 @@ private fun PersonDetailSkeleton(
|
|||
personId: Int,
|
||||
personName: String,
|
||||
profilePhoto: String? = null,
|
||||
avatarTransitionKey: String,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
) {
|
||||
val accentColor = MaterialTheme.colorScheme.primary
|
||||
val avatarCacheKey = castAvatarSharedTransitionKey(personId)
|
||||
val avatarCacheKey = avatarTransitionKey
|
||||
val platformContext = LocalPlatformContext.current
|
||||
val avatarRequest = if (!profilePhoto.isNullOrBlank()) {
|
||||
remember(platformContext, profilePhoto, avatarCacheKey) {
|
||||
|
|
@ -492,7 +500,7 @@ private fun PersonDetailSkeleton(
|
|||
with(sharedTransitionScope) {
|
||||
Modifier.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(
|
||||
key = castAvatarSharedTransitionKey(personId),
|
||||
key = avatarTransitionKey,
|
||||
),
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ fun DetailCastSection(
|
|||
cast: List<MetaPerson>,
|
||||
modifier: Modifier = Modifier,
|
||||
showHeader: Boolean = true,
|
||||
onCastClick: ((MetaPerson) -> Unit)? = null,
|
||||
onCastClick: ((MetaPerson, String?) -> Unit)? = null,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
) {
|
||||
|
|
@ -61,14 +61,18 @@ fun DetailCastSection(
|
|||
itemsIndexed(
|
||||
items = cast,
|
||||
key = { index, person -> "${person.name}-${person.role.orEmpty()}-${person.photo.orEmpty()}-$index" },
|
||||
) { _, person ->
|
||||
) { index, person ->
|
||||
val sharedTransitionKey = person.tmdbId
|
||||
?.takeIf { it > 0 }
|
||||
?.let { castAvatarSharedTransitionKey(it, occurrenceIndex = index) }
|
||||
CastItem(
|
||||
person = person,
|
||||
sharedTransitionKey = sharedTransitionKey,
|
||||
sizing = sizing,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
onClick = if (onCastClick != null && person.tmdbId != null && person.tmdbId > 0) {
|
||||
{ onCastClick(person) }
|
||||
{ onCastClick(person, sharedTransitionKey) }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
|
|
@ -84,12 +88,13 @@ fun DetailCastSection(
|
|||
private fun CastItem(
|
||||
person: MetaPerson,
|
||||
modifier: Modifier = Modifier,
|
||||
sharedTransitionKey: String? = null,
|
||||
sizing: CastSectionSizing,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) {
|
||||
val avatarCacheKey = person.tmdbId?.takeIf { it > 0 }?.let(::castAvatarSharedTransitionKey)
|
||||
val avatarCacheKey = sharedTransitionKey
|
||||
val platformContext = LocalPlatformContext.current
|
||||
val avatarRequest = if (!person.photo.isNullOrBlank() && !avatarCacheKey.isNullOrBlank()) {
|
||||
remember(platformContext, person.photo, avatarCacheKey) {
|
||||
|
|
@ -107,13 +112,12 @@ private fun CastItem(
|
|||
val avatarSharedElementModifier = if (
|
||||
sharedTransitionScope != null &&
|
||||
animatedVisibilityScope != null &&
|
||||
person.tmdbId != null &&
|
||||
person.tmdbId > 0
|
||||
!sharedTransitionKey.isNullOrBlank()
|
||||
) {
|
||||
with(sharedTransitionScope) {
|
||||
Modifier.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(
|
||||
key = castAvatarSharedTransitionKey(person.tmdbId),
|
||||
key = sharedTransitionKey,
|
||||
),
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue