mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Updates to series overview
This commit is contained in:
parent
31b4881d7c
commit
f96ed850b7
5 changed files with 83 additions and 37 deletions
|
|
@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue