diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/BannerCard.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/BannerCard.kt index a8679154..9f13ecf6 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/BannerCard.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/BannerCard.kt @@ -5,6 +5,8 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons @@ -12,6 +14,8 @@ import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -25,13 +29,14 @@ import com.github.damontecres.dolphin.ui.isNotNullOrBlank @Composable fun BannerCard( - imageUrl: String, + imageUrl: String?, cornerText: String?, played: Boolean, + playPercent: Double, onClick: () -> Unit, onLongClick: () -> Unit, modifier: Modifier = Modifier, - cardWidth: Dp = 160.dp, + cardWidth: Dp = 200.dp, cardHeight: Dp = cardWidth * 9 / 16, interactionSource: MutableInteractionSource? = null, ) { @@ -52,7 +57,10 @@ fun BannerCard( Row( horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.align(Alignment.TopEnd), + modifier = + Modifier + .align(Alignment.TopEnd) + .padding(4.dp), ) { if (played) { Icon( @@ -61,20 +69,37 @@ fun BannerCard( tint = MaterialTheme.colorScheme.border.copy(alpha = 1f), modifier = Modifier - .size(48.dp) - .padding(8.dp), + .size(24.dp), ) } if (cornerText.isNotNullOrBlank()) { - Text( - text = cornerText, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.background(AppColors.TransparentBlack50), - ) + Box( + modifier = + Modifier + .background(AppColors.TransparentBlack50), + ) { + Text( + text = cornerText, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface, + modifier = Modifier.padding(4.dp), + ) + } } } } + if (playPercent > 0 && playPercent < 100) { + Box( + modifier = + Modifier + .align(Alignment.BottomStart) + .background( + MaterialTheme.colorScheme.tertiary, + ).clip(RectangleShape) + .height(4.dp) + .fillMaxWidth((playPercent / 100).toFloat()), + ) + } } } } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt index 1289effb..3b50735d 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt @@ -103,6 +103,7 @@ class SeriesViewModel ItemFields.PRIMARY_IMAGE_ASPECT_RATIO, ItemFields.CHILD_COUNT, ItemFields.MEDIA_STREAMS, + ItemFields.OVERVIEW, ), ) val pager = ItemPager(api, request, viewModelScope) diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeFooter.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeFooter.kt index dd85fff1..71bb7483 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeFooter.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeFooter.kt @@ -117,7 +117,7 @@ fun FocusedEpisodeFooter( } Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { dto.mediaStreams ?.firstOrNull { it.type == MediaStreamType.VIDEO } @@ -133,12 +133,17 @@ fun FocusedEpisodeFooter( dto.mediaStreams ?.firstOrNull { it.type == MediaStreamType.AUDIO } ?.let { stream -> - stream.displayTitle?.let { - TitleValueText( - "Audio", - it, - ) - } + // TODO probably a cleaner way to do this + // Removes part of "5.1 Surround - English - AAC - Default" + stream.displayTitle + ?.replace(" - Default", "") + ?.ifBlank { null } + ?.let { + TitleValueText( + "Audio", + it, + ) + } } dto.mediaStreams diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt index 46ea40eb..5e9c2370 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt @@ -45,7 +45,7 @@ fun FocusedEpisodeHeader( ) { Text( text = dto.episodeTitle ?: dto.name ?: "", - style = MaterialTheme.typography.headlineMedium, + style = MaterialTheme.typography.headlineSmall, modifier = Modifier, ) Row( @@ -64,18 +64,20 @@ fun FocusedEpisodeHeader( } DotSeparatedRow( texts = details, - textStyle = MaterialTheme.typography.titleLarge, + textStyle = MaterialTheme.typography.titleSmall, ) } Row( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { - Text( - text = "Critic: ${dto.criticRating}", - style = MaterialTheme.typography.bodySmall, - modifier = Modifier, - ) + dto.criticRating?.let { + Text( + text = "Critic: ${dto.criticRating}", + style = MaterialTheme.typography.bodySmall, + modifier = Modifier, + ) + } StarRating( rating100 = dto @@ -115,11 +117,14 @@ fun FocusedEpisodeHeader( ) { Text( text = overview, - style = MaterialTheme.typography.bodyLarge, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, maxLines = 3, overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(8.dp), + modifier = + Modifier + .padding(8.dp) + .height(60.dp), ) } } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt index 2f2ece7c..880eba9c 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -38,7 +39,7 @@ import androidx.tv.material3.TabRow import androidx.tv.material3.Text import coil3.compose.AsyncImage import com.github.damontecres.dolphin.data.model.BaseItem -import com.github.damontecres.dolphin.ui.cards.ItemCard +import com.github.damontecres.dolphin.ui.cards.BannerCard import com.github.damontecres.dolphin.ui.ifElse import com.github.damontecres.dolphin.ui.isNotNullOrBlank @@ -81,7 +82,8 @@ fun SeriesOverviewContent( alignment = Alignment.TopEnd, modifier = Modifier - .fillMaxHeight(.5f) + .fillMaxHeight(.6f) + .alpha(.4f) .drawWithContent { drawContent() drawRect( @@ -110,8 +112,10 @@ fun SeriesOverviewContent( selectedTabIndex = selectedTabIndex, modifier = Modifier - .ifElse(focusRequesters.size > selectedTabIndex, { Modifier.focusRestorer(focusRequesters[selectedTabIndex]) }) - .focusRequester(tabRowFocusRequester) + .ifElse( + focusRequesters.size > selectedTabIndex, + { Modifier.focusRestorer(focusRequesters[selectedTabIndex]) }, + ).focusRequester(tabRowFocusRequester) .padding(horizontal = 16.dp) .fillMaxWidth(), ) { @@ -142,7 +146,7 @@ fun SeriesOverviewContent( series.name?.let { Text( text = it, - style = MaterialTheme.typography.headlineLarge, + style = MaterialTheme.typography.headlineMedium, modifier = Modifier, ) } @@ -155,7 +159,7 @@ fun SeriesOverviewContent( overviewOnClick = { // TODO show full overview dialog }, - modifier = Modifier, + modifier = Modifier.fillMaxWidth(.66f), ) } } @@ -165,7 +169,7 @@ fun SeriesOverviewContent( LazyRow( state = state, horizontalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = PaddingValues(start = 32.dp), + contentPadding = PaddingValues(start = 16.dp), modifier = modifier.focusRestorer(firstItemFocusRequester), ) { itemsIndexed(episodes) { index, episode -> @@ -173,8 +177,11 @@ fun SeriesOverviewContent( if (interactionSource.collectIsFocusedAsState().value) { onFocus.invoke(SeasonEpisode(selectedTabIndex, index)) } - ItemCard( - item = episode, + BannerCard( + imageUrl = episode?.imageUrl, + cornerText = "E${episode?.data?.indexNumber}", + played = episode?.data?.userData?.played ?: false, + playPercent = episode?.data?.userData?.playedPercentage ?: 0.0, onClick = { if (episode != null) onClick.invoke(episode) }, onLongClick = { if (episode != null) onLongClick.invoke(episode) }, modifier = @@ -195,7 +202,10 @@ fun SeriesOverviewContent( playOnClick = {}, moreOnClick = {}, watchOnClick = {}, - modifier = Modifier.fillMaxWidth(), + modifier = + Modifier + .fillMaxWidth() + .padding(start = 16.dp), ) } }