diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeScreen.kt index 33f471fc..f41fa984 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeScreen.kt @@ -17,6 +17,7 @@ import hu.bbara.purefin.common.ui.PurefinWaitingScreen import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection import hu.bbara.purefin.common.ui.components.MediaDetailPlaybackSection import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle +import hu.bbara.purefin.common.ui.components.TvMediaDetailBodyBox import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold import hu.bbara.purefin.core.data.navigation.LocalNavigationManager import hu.bbara.purefin.core.data.navigation.Route @@ -78,20 +79,24 @@ internal fun EpisodeScreenContent( } TvMediaDetailScaffold( - backgroundImageUrl = tvMediaDetailBackgroundImageUrl(episode.imageUrlPrefix), resetScrollKey = episode.id, - modifier = modifier, - heroContent = { - EpisodeHeroSection( - episode = episode, - seriesTitle = seriesTitle, - onPlay = onPlay, - playFocusRequester = playFocusRequester, - modifier = Modifier.fillMaxWidth() - ) - Spacer(modifier = Modifier.height(12.dp)) - } + modifier = modifier ) { + item { + TvMediaDetailBodyBox( + backgroundImageUrl = tvMediaDetailBackgroundImageUrl(episode.imageUrlPrefix), + modifier = it + ) { + EpisodeHeroSection( + episode = episode, + seriesTitle = seriesTitle, + onPlay = onPlay, + playFocusRequester = playFocusRequester, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(12.dp)) + } + } item { Column(modifier = it.fillMaxWidth()) { Spacer(modifier = Modifier.height(16.dp)) diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieScreen.kt index eb92ce28..b88d8bc5 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieScreen.kt @@ -17,6 +17,7 @@ import hu.bbara.purefin.common.ui.PurefinWaitingScreen import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection import hu.bbara.purefin.common.ui.components.MediaDetailPlaybackSection import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle +import hu.bbara.purefin.common.ui.components.TvMediaDetailBodyBox import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold import hu.bbara.purefin.common.ui.components.tvMediaDetailBackgroundImageUrl import hu.bbara.purefin.core.data.navigation.MovieDto @@ -57,19 +58,23 @@ internal fun MovieScreenContent( } TvMediaDetailScaffold( - backgroundImageUrl = tvMediaDetailBackgroundImageUrl(movie.imageUrlPrefix), resetScrollKey = movie.id, - modifier = modifier, - heroContent = { - MovieHeroSection( - movie = movie, - onPlay = onPlay, - playFocusRequester = playFocusRequester, - modifier = Modifier.fillMaxWidth() - ) - Spacer(modifier = Modifier.height(12.dp)) - } + modifier = modifier ) { + item { + TvMediaDetailBodyBox( + backgroundImageUrl = tvMediaDetailBackgroundImageUrl(movie.imageUrlPrefix), + modifier = it + ) { + MovieHeroSection( + movie = movie, + onPlay = onPlay, + playFocusRequester = playFocusRequester, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(12.dp)) + } + } item { Column(modifier = it.fillMaxWidth()) { Spacer(modifier = Modifier.height(16.dp)) diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt index 5785a666..bf387240 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt @@ -18,6 +18,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import hu.bbara.purefin.common.ui.PurefinWaitingScreen import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle +import hu.bbara.purefin.common.ui.components.TvMediaDetailBodyBox import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold import hu.bbara.purefin.common.ui.components.tvMediaDetailBackgroundImageUrl import hu.bbara.purefin.core.data.navigation.SeriesDto @@ -70,21 +71,25 @@ internal fun SeriesScreenContent( } TvMediaDetailScaffold( - backgroundImageUrl = tvMediaDetailBackgroundImageUrl(series.imageUrlPrefix), resetScrollKey = series.id, - modifier = modifier, - heroContent = { - SeriesHeroSection( - series = series, - nextUpEpisode = nextUpEpisode, - onPlayEpisode = { onPlayEpisode(it.id) }, - playFocusRequester = playFocusRequester, - firstContentFocusRequester = firstContentFocusRequester, - modifier = Modifier.fillMaxWidth() - ) - Spacer(modifier = Modifier.height(12.dp)) - } + modifier = modifier ) { + item { + TvMediaDetailBodyBox( + backgroundImageUrl = tvMediaDetailBackgroundImageUrl(series.imageUrlPrefix), + modifier = it + ) { + SeriesHeroSection( + series = series, + nextUpEpisode = nextUpEpisode, + onPlayEpisode = { onPlayEpisode(it.id) }, + playFocusRequester = playFocusRequester, + firstContentFocusRequester = firstContentFocusRequester, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(12.dp)) + } + } item { Column(modifier = it.fillMaxWidth()) { Spacer(modifier = Modifier.height(16.dp)) diff --git a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailShell.kt b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailShell.kt index 3dfe6a9a..44570825 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailShell.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailShell.kt @@ -17,6 +17,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.layout.ContentScale @@ -31,14 +32,12 @@ import org.jellyfin.sdk.model.api.ImageType internal val MediaDetailHorizontalPadding = 48.dp private val MediaDetailHeaderTopPadding = 104.dp private val MediaDetailHeaderBottomPadding = 36.dp +private const val MediaDetailBodyImageWidthFraction = 0.56f @Composable internal fun TvMediaDetailScaffold( - backgroundImageUrl: String, resetScrollKey: Any, modifier: Modifier = Modifier, - headerHeightFraction: Float = 0.48f, - heroContent: @Composable ColumnScope.() -> Unit, bodyContent: LazyListScope.(Modifier) -> Unit = { _ -> } ) { val scheme = MaterialTheme.colorScheme @@ -55,36 +54,33 @@ internal fun TvMediaDetailScaffold( .fillMaxSize() .background(scheme.background) ) { - item { - TvMediaDetailHeader( - backgroundImageUrl = backgroundImageUrl, - headerHeightFraction = headerHeightFraction, - heroContent = heroContent - ) - } bodyContent(contentPadding) } } @Composable -private fun TvMediaDetailHeader( +internal fun TvMediaDetailBodyBox( backgroundImageUrl: String, - headerHeightFraction: Float, - heroContent: @Composable ColumnScope.() -> Unit + modifier: Modifier = Modifier, + heightFraction: Float = 0.48f, + content: @Composable ColumnScope.() -> Unit ) { val scheme = MaterialTheme.colorScheme val screenHeight = LocalConfiguration.current.screenHeightDp.dp - val headerHeight = screenHeight * headerHeightFraction + val bodyHeight = screenHeight * heightFraction Box( - modifier = Modifier + modifier = modifier .fillMaxWidth() - .heightIn(min = headerHeight) + .heightIn(min = bodyHeight) ) { PurefinAsyncImage( model = backgroundImageUrl, contentDescription = null, - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .fillMaxWidth(MediaDetailBodyImageWidthFraction) + .align(Alignment.TopEnd), contentScale = ContentScale.Crop ) Box( @@ -118,13 +114,11 @@ private fun TvMediaDetailHeader( modifier = Modifier .fillMaxWidth() .padding( - start = MediaDetailHorizontalPadding, top = MediaDetailHeaderTopPadding, - end = MediaDetailHorizontalPadding, bottom = MediaDetailHeaderBottomPadding ) ) { - heroContent() + content() } } }