diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/common/media/MediaDetailShell.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/common/media/MediaDetailShell.kt index d746f510..fbb9bcc2 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/common/media/MediaDetailShell.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/common/media/MediaDetailShell.kt @@ -32,8 +32,8 @@ import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.ui.common.image.PurefinAsyncImage internal val MediaDetailHorizontalPadding = 48.dp -private val MediaDetailHeaderTopPadding = 24.dp -private val MediaDetailHeaderBottomPadding = 24.dp +private val MediaDetailHeaderTopPadding = 6.dp +private val MediaDetailHeaderBottomPadding = 4.dp private const val MediaDetailBodyImageWidthFraction = 0.66f internal val TvMediaDetailBringIntoViewSpec: BringIntoViewSpec = @@ -77,7 +77,7 @@ internal fun TvMediaDetailScaffold( internal fun TvMediaDetailBodyBox( backgroundImageUrl: String, modifier: Modifier = Modifier, - heightFraction: Float = 0.48f, + heightFraction: Float = 0.24f, content: @Composable ColumnScope.() -> Unit ) { val scheme = MaterialTheme.colorScheme @@ -173,12 +173,11 @@ internal fun MediaDetailOverviewSection( title = "Overview", titleColor = scheme.onBackground, bodyColor = scheme.onSurfaceVariant.copy(alpha = 0.85f), - titleFontSize = 22.sp, - bodyFontSize = 16.sp, - bodyLineHeight = 24.sp, - titleSpacing = 14.dp, - collapsedLines = 5, - collapseInitially = false + titleFontSize = 15.sp, + bodyFontSize = 11.sp, + bodyLineHeight = 14.sp, + titleSpacing = 2.dp, + collapsedLines = 1 ) } diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt index 62484ea5..a5928491 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt @@ -99,15 +99,15 @@ internal fun TvEpisodeScreenContent( playFocusRequester = playFocusRequester, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(2.dp)) } Column(modifier = it.fillMaxWidth()) { - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(4.dp)) MediaDetailOverviewSection( synopsis = episode.synopsis, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(8.dp)) } Column(modifier = it.fillMaxWidth()) { MediaDetailPlaybackSection( @@ -115,7 +115,7 @@ internal fun TvEpisodeScreenContent( subtitles = "ENG", modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(8.dp)) } Column(modifier = it.fillMaxWidth()) { MediaDetailSectionTitle(text = "Cast") @@ -125,4 +125,3 @@ internal fun TvEpisodeScreenContent( } } } - diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/components/TvEpisodeComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/components/TvEpisodeComponents.kt index 6e1d61d9..3673707f 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/components/TvEpisodeComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/components/TvEpisodeComponents.kt @@ -39,47 +39,47 @@ internal fun TvEpisodeHeroSection( Column( modifier = modifier .fillMaxWidth() - .widthIn(max = 760.dp) + .widthIn(max = 560.dp) ) { if (!seriesTitle.isNullOrBlank()) { Text( text = seriesTitle, color = scheme.primary, - fontSize = 18.sp, + fontSize = 12.sp, fontWeight = FontWeight.SemiBold, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(2.dp)) } Text( text = episode.title, color = scheme.onBackground, - fontSize = 42.sp, + fontSize = 24.sp, fontWeight = FontWeight.Bold, - lineHeight = 48.sp, - maxLines = 2, + lineHeight = 28.sp, + maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(2.dp)) Text( text = "Episode ${episode.index}", color = mutedStrong, - fontSize = 18.sp, + fontSize = 10.sp, fontWeight = FontWeight.Medium ) - Spacer(modifier = Modifier.height(18.dp)) + Spacer(modifier = Modifier.height(4.dp)) MediaMetadataFlowRow( items = listOf(episode.releaseDate, episode.rating, episode.runtime, episode.format), highlightedItem = episode.format ) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(6.dp)) MediaResumeButton( text = mediaPlayButtonText(episode.progress, episode.watched), progress = mediaPlaybackProgress(episode.progress), onClick = onPlay, modifier = Modifier - .sizeIn(minWidth = 216.dp, maxWidth = 240.dp) + .sizeIn(minWidth = 160.dp, maxWidth = 192.dp) .focusRequester(playFocusRequester) .testTag(EpisodePlayButtonTag), focusedScale = 1.08f, @@ -88,7 +88,10 @@ internal fun TvEpisodeHeroSection( focusBorderColor = scheme.onBackground, overlayBorderWidth = 2.dp, overlayBorderColor = scheme.primary.copy(alpha = 0.95f), - focusable = true + focusable = true, + height = 40.dp, + textSize = 13.sp, + iconSize = 20.dp ) } } diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt index 8112196a..28c344c5 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt @@ -67,7 +67,7 @@ internal fun TvMovieScreenContent( ) { TvMediaDetailBodyBox( backgroundImageUrl = tvMediaDetailBackgroundImageUrl(movie.imageUrlPrefix), - modifier = Modifier + modifier = it ) { TvMovieHeroSection( movie = movie, @@ -75,31 +75,31 @@ internal fun TvMovieScreenContent( playFocusRequester = playFocusRequester, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(2.dp)) } - Column(modifier = Modifier.fillMaxWidth()) { - Spacer(modifier = Modifier.height(16.dp)) + Column(modifier = it.fillMaxWidth()) { + Spacer(modifier = Modifier.height(4.dp)) MediaDetailOverviewSection( synopsis = movie.synopsis, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(8.dp)) } - } - Column(modifier = Modifier.fillMaxWidth()) { - MediaDetailPlaybackSection( - audioTrack = "ENG", - subtitles = "ENG", - modifier = Modifier.fillMaxWidth() - ) - Spacer(modifier = Modifier.height(20.dp)) - } - if (movie.cast.isNotEmpty()) { - Column(modifier = Modifier.fillMaxWidth()) { - MediaDetailSectionTitle(text = "Cast") - Spacer(modifier = Modifier.height(14.dp)) + Column(modifier = it.fillMaxWidth()) { + MediaDetailPlaybackSection( + audioTrack = "ENG", + subtitles = "ENG", + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(8.dp)) + } + if (movie.cast.isNotEmpty()) { + Column(modifier = it.fillMaxWidth()) { + MediaDetailSectionTitle(text = "Cast") + Spacer(modifier = Modifier.height(14.dp)) // MediaCastRow(cast = movie.cast) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(24.dp)) + } } } } diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/components/TvMovieComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/components/TvMovieComponents.kt index fbe9a943..47906a1e 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/components/TvMovieComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/components/TvMovieComponents.kt @@ -37,29 +37,29 @@ internal fun TvMovieHeroSection( Column( modifier = modifier .fillMaxWidth() - .widthIn(max = 760.dp) + .widthIn(max = 560.dp) ) { Text( text = movie.title, color = scheme.onBackground, - fontSize = 42.sp, + fontSize = 24.sp, fontWeight = FontWeight.Bold, - lineHeight = 48.sp, - maxLines = 2, + lineHeight = 28.sp, + maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(18.dp)) + Spacer(modifier = Modifier.height(4.dp)) MediaMetadataFlowRow( items = listOf(movie.year, movie.rating, movie.runtime, movie.format), highlightedItem = movie.format ) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(6.dp)) MediaResumeButton( text = mediaPlayButtonText(movie.progress, movie.watched), progress = mediaPlaybackProgress(movie.progress), onClick = onPlay, modifier = Modifier - .sizeIn(minWidth = 216.dp, maxWidth = 240.dp) + .sizeIn(minWidth = 160.dp, maxWidth = 192.dp) .focusRequester(playFocusRequester) .testTag(MoviePlayButtonTag), focusedScale = 1.08f, @@ -68,7 +68,10 @@ internal fun TvMovieHeroSection( focusBorderColor = scheme.onBackground, overlayBorderWidth = 2.dp, overlayBorderColor = scheme.primary.copy(alpha = 0.95f), - focusable = true + focusable = true, + height = 40.dp, + textSize = 13.sp, + iconSize = 20.dp ) } } diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt index 002e9fc4..2e054e40 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt @@ -93,15 +93,15 @@ internal fun TvSeriesScreenContent( firstContentFocusRequester = firstContentFocusRequester, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(2.dp)) } Column(modifier = it.fillMaxWidth()) { - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(4.dp)) MediaDetailOverviewSection( synopsis = series.synopsis, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(8.dp)) } TvSeasonTabs( seasons = series.seasons, @@ -111,7 +111,7 @@ internal fun TvSeriesScreenContent( onSelect = { selectedSeason = it }, modifier = it ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(8.dp)) TvEpisodeCarousel( episodes = selectedSeason.episodes, modifier = it @@ -128,7 +128,6 @@ internal fun TvSeriesScreenContent( } } - private fun Series.defaultSeason(): Season { for (season in seasons) { if (season.episodes.any { !it.watched }) { diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt index dd50e297..6bff72e0 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt @@ -191,54 +191,53 @@ internal fun TvSeriesHeroSection( Column( modifier = modifier .fillMaxWidth() - .widthIn(max = 760.dp) + .widthIn(max = 560.dp) ) { Text( text = series.name, color = scheme.onBackground, - fontSize = 42.sp, + fontSize = 24.sp, fontWeight = FontWeight.Bold, - lineHeight = 48.sp, - maxLines = 2, + lineHeight = 28.sp, + maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(18.dp)) + Spacer(modifier = Modifier.height(4.dp)) TvSeriesMetaChips(series = series) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(6.dp)) if (nextUpEpisode != null) { Text( text = nextUpEpisode.heroStatusText(), color = scheme.primary, - fontSize = 18.sp, + fontSize = 12.sp, fontWeight = FontWeight.SemiBold, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(2.dp)) Text( text = nextUpEpisode.title, color = scheme.onBackground, - fontSize = 22.sp, + fontSize = 14.sp, fontWeight = FontWeight.SemiBold, - maxLines = 2, + maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(6.dp)) Text( text = "Episode ${nextUpEpisode.index} • ${nextUpEpisode.runtime}", color = mutedStrong, - fontSize = 14.sp, + fontSize = 10.sp, fontWeight = FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(6.dp)) MediaResumeButton( text = mediaPlayButtonText(nextUpEpisode.progress, nextUpEpisode.watched), progress = mediaPlaybackProgress(nextUpEpisode.progress), onClick = { onPlayEpisode(nextUpEpisode) }, modifier = Modifier - .sizeIn(minWidth = 216.dp, maxWidth = 240.dp) + .sizeIn(minWidth = 160.dp, maxWidth = 192.dp) .focusRequester(playFocusRequester) .focusProperties { down = firstContentFocusRequester } .testTag(SeriesPlayButtonTag), @@ -248,13 +247,16 @@ internal fun TvSeriesHeroSection( focusBorderColor = scheme.onBackground, overlayBorderWidth = 2.dp, overlayBorderColor = scheme.primary.copy(alpha = 0.95f), - focusable = true + focusable = true, + height = 40.dp, + textSize = 13.sp, + iconSize = 20.dp ) } else { Text( text = "Choose a season below to start watching.", color = mutedStrong, - fontSize = 16.sp, + fontSize = 12.sp, fontWeight = FontWeight.Medium ) } diff --git a/core-ui/src/main/java/hu/bbara/purefin/ui/common/button/MediaResumeButton.kt b/core-ui/src/main/java/hu/bbara/purefin/ui/common/button/MediaResumeButton.kt index 53008e1d..a1bd8c26 100644 --- a/core-ui/src/main/java/hu/bbara/purefin/ui/common/button/MediaResumeButton.kt +++ b/core-ui/src/main/java/hu/bbara/purefin/ui/common/button/MediaResumeButton.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons @@ -35,6 +36,7 @@ import androidx.compose.ui.graphics.drawscope.clipRect import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -50,7 +52,10 @@ fun MediaResumeButton( focusBorderColor: Color = Color.Transparent, overlayBorderWidth: Dp = 0.dp, overlayBorderColor: Color = Color.Transparent, - focusable: Boolean = false + focusable: Boolean = false, + height: Dp = 52.dp, + textSize: TextUnit = 16.sp, + iconSize: Dp = 24.dp ) { val scheme = MaterialTheme.colorScheme val primaryColor = scheme.primary @@ -73,7 +78,7 @@ fun MediaResumeButton( BoxWithConstraints( modifier = modifier .graphicsLayer { scaleX = scale; scaleY = scale } - .height(52.dp) + .height(height) .background(haloColor, shape) .border( width = if (isFocused) focusBorderWidth else 0.dp, @@ -91,7 +96,12 @@ fun MediaResumeButton( .background(onPrimaryColor), contentAlignment = Alignment.Center ) { - ResumeButtonContent(text = text, color = primaryColor) + ResumeButtonContent( + text = text, + color = primaryColor, + textSize = textSize, + iconSize = iconSize + ) } Box( @@ -111,7 +121,12 @@ fun MediaResumeButton( .background(primaryColor), contentAlignment = Alignment.Center ) { - ResumeButtonContent(text = text, color = onPrimaryColor) + ResumeButtonContent( + text = text, + color = onPrimaryColor, + textSize = textSize, + iconSize = iconSize + ) } if (isFocused && overlayBorderWidth > 0.dp) { @@ -125,13 +140,23 @@ fun MediaResumeButton( } @Composable -private fun ResumeButtonContent(text: String, color: Color) { +private fun ResumeButtonContent( + text: String, + color: Color, + textSize: TextUnit, + iconSize: Dp +) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { - Text(text, color = color, fontWeight = FontWeight.Bold, fontSize = 16.sp) + Text(text, color = color, fontWeight = FontWeight.Bold, fontSize = textSize) Spacer(Modifier.width(8.dp)) - Icon(Icons.Filled.PlayArrow, null, tint = color) + Icon( + imageVector = Icons.Filled.PlayArrow, + contentDescription = null, + tint = color, + modifier = Modifier.size(iconSize) + ) } }