Refine series download actions

This commit is contained in:
2026-03-17 18:18:05 +01:00
parent 43a15c4662
commit 08cc4589c2
3 changed files with 51 additions and 67 deletions

View File

@@ -33,7 +33,6 @@ import androidx.compose.material.icons.outlined.Cast
import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.DownloadDone import androidx.compose.material.icons.outlined.DownloadDone
import androidx.compose.material.icons.outlined.Autorenew
import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.PlayCircle import androidx.compose.material.icons.outlined.PlayCircle
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
@@ -121,10 +120,10 @@ internal fun SeriesMetaChips(series: Series) {
@Composable @Composable
internal fun SeriesActionButtons( internal fun SeriesActionButtons(
nextUpEpisode: Episode?, nextUpEpisode: Episode?,
downloadState: DownloadState, seriesDownloadState: DownloadState,
isSmartDownloadEnabled: Boolean, selectedSeason: Season,
onDownloadAllClick: () -> Unit, seasonDownloadState: DownloadState,
onSmartDownloadToggle: () -> Unit, onDownloadOptionSelected: (SeriesDownloadOption) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -158,12 +157,11 @@ internal fun SeriesActionButtons(
) )
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
MediaActionButton( MediaActionButton(
backgroundColor = if (isSmartDownloadEnabled) scheme.primary else scheme.secondary, backgroundColor = scheme.secondary,
iconColor = if (isSmartDownloadEnabled) scheme.onPrimary else scheme.onSecondary, iconColor = scheme.onSecondary,
icon = when { icon = when {
isSmartDownloadEnabled -> Icons.Outlined.Autorenew seriesDownloadState is DownloadState.Downloading -> Icons.Outlined.Close
downloadState is DownloadState.Downloading -> Icons.Outlined.Close seriesDownloadState is DownloadState.Downloaded -> Icons.Outlined.DownloadDone
downloadState is DownloadState.Downloaded -> Icons.Outlined.DownloadDone
else -> Icons.Outlined.Download else -> Icons.Outlined.Download
}, },
height = 32.dp, height = 32.dp,
@@ -173,25 +171,28 @@ internal fun SeriesActionButtons(
if (showDownloadDialog) { if (showDownloadDialog) {
DownloadOptionsDialog( DownloadOptionsDialog(
isSmartDownloadEnabled = isSmartDownloadEnabled, selectedSeasonName = selectedSeason.name,
onDownloadAll = { seasonDownloadState = seasonDownloadState,
onDownloadOptionSelected = {
showDownloadDialog = false showDownloadDialog = false
onDownloadAllClick() onDownloadOptionSelected(it)
},
onSmartDownload = {
showDownloadDialog = false
onSmartDownloadToggle()
}, },
onDismiss = { showDownloadDialog = false } onDismiss = { showDownloadDialog = false }
) )
} }
} }
internal enum class SeriesDownloadOption {
SEASON,
SERIES,
SMART
}
@Composable @Composable
private fun DownloadOptionsDialog( private fun DownloadOptionsDialog(
isSmartDownloadEnabled: Boolean, selectedSeasonName: String,
onDownloadAll: () -> Unit, seasonDownloadState: DownloadState,
onSmartDownload: () -> Unit, onDownloadOptionSelected: (SeriesDownloadOption) -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
AlertDialog( AlertDialog(
@@ -203,24 +204,27 @@ private fun DownloadOptionsDialog(
text = "Choose how to download this series.", text = "Choose how to download this series.",
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium
) )
if (isSmartDownloadEnabled) {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "Smart download is currently enabled.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary
)
}
} }
}, },
confirmButton = { confirmButton = {
TextButton(onClick = onDownloadAll) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Text("Download All") TextButton(onClick = { onDownloadOptionSelected(SeriesDownloadOption.SEASON) }) {
Text(
when (seasonDownloadState) {
is DownloadState.Downloaded -> "$selectedSeasonName Downloaded"
is DownloadState.Downloading -> "Downloading $selectedSeasonName"
else -> "Download $selectedSeasonName"
}
)
}
TextButton(onClick = { onDownloadOptionSelected(SeriesDownloadOption.SERIES) }) {
Text("Download All")
}
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = onSmartDownload) { TextButton(onClick = { onDownloadOptionSelected(SeriesDownloadOption.SMART) }) {
Text(if (isSmartDownloadEnabled) "Disable Smart Download" else "Smart Download") Text("Smart Download")
} }
} }
) )
@@ -230,8 +234,6 @@ private fun DownloadOptionsDialog(
internal fun SeasonTabs( internal fun SeasonTabs(
seasons: List<Season>, seasons: List<Season>,
selectedSeason: Season?, selectedSeason: Season?,
seasonDownloadState: DownloadState,
onSeasonDownloadClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onSelect: (Season) -> Unit onSelect: (Season) -> Unit
) { ) {
@@ -249,18 +251,6 @@ internal fun SeasonTabs(
modifier = Modifier.clickable { onSelect(season) } modifier = Modifier.clickable { onSelect(season) }
) )
} }
MediaActionButton(
backgroundColor = MaterialTheme.colorScheme.secondary,
iconColor = MaterialTheme.colorScheme.onSecondary,
icon = when (seasonDownloadState) {
is DownloadState.NotDownloaded -> Icons.Outlined.Download
is DownloadState.Downloading -> Icons.Outlined.Close
is DownloadState.Downloaded -> Icons.Outlined.DownloadDone
is DownloadState.Failed -> Icons.Outlined.Download
},
height = 28.dp,
onClick = onSeasonDownloadClick
)
} }
} }

View File

@@ -89,8 +89,6 @@ private fun SeriesScreenInternal(
val seriesDownloadState by viewModel.seriesDownloadState.collectAsState() val seriesDownloadState by viewModel.seriesDownloadState.collectAsState()
val seasonDownloadState by viewModel.seasonDownloadState.collectAsState() val seasonDownloadState by viewModel.seasonDownloadState.collectAsState()
val isSmartDownloadEnabled by viewModel.isSmartDownloadEnabled.collectAsState()
LaunchedEffect(selectedSeason.value) { LaunchedEffect(selectedSeason.value) {
viewModel.observeSeasonDownloadState(selectedSeason.value.episodes) viewModel.observeSeasonDownloadState(selectedSeason.value.episodes)
} }
@@ -134,10 +132,19 @@ private fun SeriesScreenInternal(
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
SeriesActionButtons( SeriesActionButtons(
nextUpEpisode = nextUpEpisode, nextUpEpisode = nextUpEpisode,
downloadState = seriesDownloadState, seriesDownloadState = seriesDownloadState,
isSmartDownloadEnabled = isSmartDownloadEnabled, selectedSeason = selectedSeason.value,
onDownloadAllClick = { viewModel.downloadSeries(series) }, seasonDownloadState = seasonDownloadState,
onSmartDownloadToggle = { viewModel.toggleSmartDownload(series.id) } onDownloadOptionSelected = { option ->
when (option) {
SeriesDownloadOption.SEASON ->
viewModel.downloadSeason(selectedSeason.value.episodes)
SeriesDownloadOption.SERIES ->
viewModel.downloadSeries(series)
SeriesDownloadOption.SMART ->
viewModel.enableSmartDownload(series.id)
}
}
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
MediaSynopsis( MediaSynopsis(
@@ -151,8 +158,6 @@ private fun SeriesScreenInternal(
SeasonTabs( SeasonTabs(
seasons = series.seasons, seasons = series.seasons,
selectedSeason = selectedSeason.value, selectedSeason = selectedSeason.value,
seasonDownloadState = seasonDownloadState,
onSeasonDownloadClick = { viewModel.downloadSeason(selectedSeason.value.episodes) },
onSelect = { selectedSeason.value = it } onSelect = { selectedSeason.value = it }
) )
EpisodeCarousel( EpisodeCarousel(

View File

@@ -39,13 +39,6 @@ class SeriesViewModel @Inject constructor(
} }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
@OptIn(ExperimentalCoroutinesApi::class)
val isSmartDownloadEnabled: StateFlow<Boolean> = _seriesId
.flatMapLatest { id ->
if (id != null) mediaDownloadManager.isSmartDownloadEnabled(id) else flowOf(false)
}
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), false)
private val _seriesDownloadState = MutableStateFlow<DownloadState>(DownloadState.NotDownloaded) private val _seriesDownloadState = MutableStateFlow<DownloadState>(DownloadState.NotDownloaded)
val seriesDownloadState: StateFlow<DownloadState> = _seriesDownloadState val seriesDownloadState: StateFlow<DownloadState> = _seriesDownloadState
@@ -83,13 +76,9 @@ class SeriesViewModel @Inject constructor(
} }
} }
fun toggleSmartDownload(seriesId: UUID) { fun enableSmartDownload(seriesId: UUID) {
viewModelScope.launch { viewModelScope.launch {
if (isSmartDownloadEnabled.value) { mediaDownloadManager.enableSmartDownload(seriesId)
mediaDownloadManager.disableSmartDownload(seriesId)
} else {
mediaDownloadManager.enableSmartDownload(seriesId)
}
} }
} }