mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
feat(series): improve season and episode loading handling
This commit is contained in:
@@ -87,7 +87,7 @@ fun SeriesScreen(
|
||||
}
|
||||
|
||||
val seriesData = seriesState.value
|
||||
if (seriesData != null && seriesData.seasons.isNotEmpty()) {
|
||||
if (seriesData != null) {
|
||||
LaunchedEffect(seriesData) {
|
||||
viewModel.observeSeriesDownloadState(seriesData)
|
||||
}
|
||||
@@ -170,22 +170,22 @@ private fun SeriesScreenInternal(
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
|
||||
fun getDefaultSeason(): Season {
|
||||
return series.seasons.firstOrNull { it.unwatchedEpisodeCount > 0 } ?: series.seasons.first()
|
||||
fun getDefaultSeason(): Season? {
|
||||
return series.seasons.firstOrNull { it.unwatchedEpisodeCount > 0 } ?: series.seasons.firstOrNull()
|
||||
}
|
||||
|
||||
var selectedSeasonId by remember(series.id) { mutableStateOf(getDefaultSeason().id) }
|
||||
var selectedSeasonId by remember(series.id) { mutableStateOf(getDefaultSeason()?.id) }
|
||||
val selectedSeason =
|
||||
series.seasons.firstOrNull { it.id == selectedSeasonId } ?: getDefaultSeason()
|
||||
val nextUpEpisode = selectedSeason.episodes.firstOrNull { !it.watched }
|
||||
?: selectedSeason.episodes.firstOrNull()
|
||||
val nextUpEpisode = selectedSeason?.episodes?.firstOrNull { !it.watched }
|
||||
?: selectedSeason?.episodes?.firstOrNull()
|
||||
|
||||
LaunchedEffect(series.id, selectedSeason.id) {
|
||||
onLoadSeasonEpisodes(series.id, selectedSeason.id)
|
||||
LaunchedEffect(series.id, selectedSeason?.id) {
|
||||
selectedSeason?.let { onLoadSeasonEpisodes(series.id, it.id) }
|
||||
}
|
||||
|
||||
LaunchedEffect(selectedSeason.id, selectedSeason.episodes) {
|
||||
onObserveSeasonDownloadState(selectedSeason.episodes)
|
||||
LaunchedEffect(selectedSeason?.id, selectedSeason?.episodes) {
|
||||
selectedSeason?.let { onObserveSeasonDownloadState(it.episodes) }
|
||||
}
|
||||
|
||||
MediaDetailScaffold(
|
||||
@@ -198,17 +198,19 @@ private fun SeriesScreenInternal(
|
||||
SeriesHeroContent(series = series)
|
||||
}
|
||||
) {
|
||||
SeriesActionButtons(
|
||||
nextUpEpisode = nextUpEpisode,
|
||||
selectedSeason = selectedSeason,
|
||||
seriesDownloadState = seriesDownloadState,
|
||||
seasonDownloadState = seasonDownloadState,
|
||||
isSmartDownloadEnabled = isSmartDownloadEnabled,
|
||||
offline = offline,
|
||||
onDownloadOptionSelected = { option ->
|
||||
onDownloadOptionSelected(option, selectedSeason)
|
||||
}
|
||||
)
|
||||
if (selectedSeason != null) {
|
||||
SeriesActionButtons(
|
||||
nextUpEpisode = nextUpEpisode,
|
||||
selectedSeason = selectedSeason,
|
||||
seriesDownloadState = seriesDownloadState,
|
||||
seasonDownloadState = seasonDownloadState,
|
||||
isSmartDownloadEnabled = isSmartDownloadEnabled,
|
||||
offline = offline,
|
||||
onDownloadOptionSelected = { option ->
|
||||
onDownloadOptionSelected(option, selectedSeason)
|
||||
}
|
||||
)
|
||||
}
|
||||
MediaSynopsis(
|
||||
synopsis = series.synopsis,
|
||||
bodyColor = scheme.onSurface,
|
||||
@@ -216,14 +218,22 @@ private fun SeriesScreenInternal(
|
||||
bodyLineHeight = null,
|
||||
titleSpacing = 8.dp
|
||||
)
|
||||
SeasonTabs(
|
||||
seasons = series.seasons,
|
||||
selectedSeason = selectedSeason,
|
||||
onSelect = { selectedSeasonId = it.id }
|
||||
)
|
||||
EpisodeCarousel(
|
||||
episodes = selectedSeason.episodes,
|
||||
)
|
||||
if (selectedSeason != null) {
|
||||
SeasonTabs(
|
||||
seasons = series.seasons,
|
||||
selectedSeason = selectedSeason,
|
||||
onSelect = { selectedSeasonId = it.id }
|
||||
)
|
||||
EpisodeCarousel(
|
||||
episodes = selectedSeason.episodes,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = "Loading seasons...",
|
||||
color = scheme.onSurfaceVariant,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
}
|
||||
if (series.cast.isNotEmpty()) {
|
||||
Text(
|
||||
text = "Cast",
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Intent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -20,8 +19,8 @@ import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
@@ -333,14 +332,23 @@ internal fun SeasonTabs(
|
||||
modifier: Modifier = Modifier,
|
||||
onSelect: (Season) -> Unit
|
||||
) {
|
||||
Row(
|
||||
val selectedSeasonIndex = seasons.indexOf(selectedSeason).coerceAtLeast(0)
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
LaunchedEffect(selectedSeasonIndex, seasons.size) {
|
||||
if (seasons.isNotEmpty()) {
|
||||
listState.scrollToItem(selectedSeasonIndex)
|
||||
}
|
||||
}
|
||||
|
||||
LazyRow(
|
||||
state = listState,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(20.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
seasons.forEachIndexed { index, season ->
|
||||
itemsIndexed(seasons, key = { _, season -> season.id }) { index, season ->
|
||||
SeasonTab(
|
||||
name = season.name,
|
||||
isSelected = season == selectedSeason,
|
||||
|
||||
Reference in New Issue
Block a user