mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
feat: add smart download management with enable and delete options
This commit is contained in:
@@ -60,6 +60,7 @@ fun SeriesScreen(
|
||||
series = seriesData,
|
||||
seriesDownloadState = viewModel.seriesDownloadState.collectAsState().value,
|
||||
seasonDownloadState = viewModel.seasonDownloadState.collectAsState().value,
|
||||
isSmartDownloadEnabled = viewModel.isSmartDownloadEnabled.collectAsState().value,
|
||||
onDownloadOptionSelected = { option, selectedSeason ->
|
||||
when (option) {
|
||||
SeriesDownloadOption.SEASON ->
|
||||
@@ -70,6 +71,9 @@ fun SeriesScreen(
|
||||
|
||||
SeriesDownloadOption.SMART ->
|
||||
viewModel.enableSmartDownload(seriesData.id)
|
||||
|
||||
SeriesDownloadOption.DELETE_SMART ->
|
||||
viewModel.deleteSmartDownloads(seriesData.id)
|
||||
}
|
||||
},
|
||||
onLoadSeasonEpisodes = viewModel::loadSeasonEpisodes,
|
||||
@@ -88,6 +92,7 @@ private fun SeriesScreenInternal(
|
||||
series: Series,
|
||||
seriesDownloadState: DownloadState,
|
||||
seasonDownloadState: DownloadState,
|
||||
isSmartDownloadEnabled: Boolean,
|
||||
onDownloadOptionSelected: (SeriesDownloadOption, Season) -> Unit,
|
||||
onLoadSeasonEpisodes: (UUID, UUID) -> Unit,
|
||||
onObserveSeasonDownloadState: (List<Episode>) -> Unit,
|
||||
@@ -130,6 +135,7 @@ private fun SeriesScreenInternal(
|
||||
seriesDownloadState = seriesDownloadState,
|
||||
selectedSeason = selectedSeason,
|
||||
seasonDownloadState = seasonDownloadState,
|
||||
isSmartDownloadEnabled = isSmartDownloadEnabled,
|
||||
offline = offline,
|
||||
onDownloadOptionSelected = { option ->
|
||||
onDownloadOptionSelected(option, selectedSeason)
|
||||
@@ -188,6 +194,7 @@ private fun SeriesScreenPreview() {
|
||||
series = previewSeries(),
|
||||
seriesDownloadState = DownloadState.Downloading(progressPercent = 0.58f),
|
||||
seasonDownloadState = DownloadState.NotDownloaded,
|
||||
isSmartDownloadEnabled = true,
|
||||
onDownloadOptionSelected = { _, _ -> },
|
||||
onLoadSeasonEpisodes = { _, _ -> },
|
||||
onObserveSeasonDownloadState = {},
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.compose.material.icons.outlined.DownloadDone
|
||||
import androidx.compose.material.icons.outlined.MoreVert
|
||||
import androidx.compose.material.icons.outlined.PlayCircle
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -112,6 +113,7 @@ internal fun SeriesActionButtons(
|
||||
seriesDownloadState: DownloadState,
|
||||
selectedSeason: Season,
|
||||
seasonDownloadState: DownloadState,
|
||||
isSmartDownloadEnabled: Boolean,
|
||||
offline: Boolean,
|
||||
onDownloadOptionSelected: (SeriesDownloadOption) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -171,6 +173,7 @@ internal fun SeriesActionButtons(
|
||||
DownloadOptionsDialog(
|
||||
selectedSeasonName = selectedSeason.name,
|
||||
seasonDownloadState = seasonDownloadState,
|
||||
isSmartDownloadEnabled = isSmartDownloadEnabled,
|
||||
onDownloadOptionSelected = {
|
||||
showDownloadDialog = false
|
||||
onDownloadOptionSelected(it)
|
||||
@@ -183,13 +186,15 @@ internal fun SeriesActionButtons(
|
||||
internal enum class SeriesDownloadOption {
|
||||
SEASON,
|
||||
SERIES,
|
||||
SMART
|
||||
SMART,
|
||||
DELETE_SMART
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DownloadOptionsDialog(
|
||||
selectedSeasonName: String,
|
||||
seasonDownloadState: DownloadState,
|
||||
isSmartDownloadEnabled: Boolean,
|
||||
onDownloadOptionSelected: (SeriesDownloadOption) -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
@@ -221,10 +226,21 @@ private fun DownloadOptionsDialog(
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
if (isSmartDownloadEnabled) {
|
||||
TextButton(
|
||||
onClick = { onDownloadOptionSelected(SeriesDownloadOption.DELETE_SMART) },
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error
|
||||
)
|
||||
) {
|
||||
Text("Delete Smart Downloads")
|
||||
}
|
||||
} else {
|
||||
TextButton(onClick = { onDownloadOptionSelected(SeriesDownloadOption.SMART) }) {
|
||||
Text("Smart Download")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,5 +13,7 @@ interface MediaDownloadController {
|
||||
suspend fun downloadEpisodes(episodeIds: List<UUID>)
|
||||
suspend fun cancelEpisodeDownload(episodeId: UUID)
|
||||
suspend fun enableSmartDownload(seriesId: UUID)
|
||||
suspend fun deleteSmartDownloads(seriesId: UUID)
|
||||
fun isSmartDownloadEnabled(seriesId: UUID): Flow<Boolean>
|
||||
suspend fun syncSmartDownloads()
|
||||
}
|
||||
|
||||
@@ -206,11 +206,16 @@ class MediaDownloadManager @Inject constructor(
|
||||
syncSmartDownloadsForSeries(seriesId)
|
||||
}
|
||||
|
||||
suspend fun disableSmartDownload(seriesId: UUID) {
|
||||
override suspend fun deleteSmartDownloads(seriesId: UUID) {
|
||||
withContext(Dispatchers.IO) {
|
||||
smartDownloadStore.disable(seriesId)
|
||||
offlineCatalogStore.getEpisodesBySeries(seriesId).forEach { episode ->
|
||||
cancelEpisodeDownload(episode.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isSmartDownloadEnabled(seriesId: UUID): Flow<Boolean> = smartDownloadStore.observe(seriesId)
|
||||
override fun isSmartDownloadEnabled(seriesId: UUID): Flow<Boolean> = smartDownloadStore.observe(seriesId)
|
||||
|
||||
override suspend fun syncSmartDownloads() {
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
@@ -88,9 +88,15 @@ class EpisodeScreenViewModel @Inject constructor(
|
||||
is DownloadState.NotDownloaded, is DownloadState.Failed -> {
|
||||
mediaDownloadManager.downloadEpisode(episodeId)
|
||||
}
|
||||
is DownloadState.Downloading, is DownloadState.Downloaded -> {
|
||||
is DownloadState.Downloading -> {
|
||||
mediaDownloadManager.cancelEpisodeDownload(episodeId)
|
||||
}
|
||||
is DownloadState.Downloaded -> {
|
||||
mediaDownloadManager.cancelEpisodeDownload(episodeId)
|
||||
if (_episode.value?.offline == true) {
|
||||
navigationManager.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ class MovieScreenViewModel @Inject constructor(
|
||||
}
|
||||
is DownloadState.Downloaded -> {
|
||||
mediaDownloadManager.cancelDownload(movieId)
|
||||
if (_movie.value?.offline == true) {
|
||||
navigationManager.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,17 @@ class SeriesViewModel @Inject constructor(
|
||||
}
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val isSmartDownloadEnabled: StateFlow<Boolean> = _series
|
||||
.flatMapLatest { series ->
|
||||
if (series == null) {
|
||||
flowOf(false)
|
||||
} else {
|
||||
mediaDownloadManager.isSmartDownloadEnabled(series.id)
|
||||
}
|
||||
}
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), false)
|
||||
|
||||
private val _seriesDownloadState = MutableStateFlow<DownloadState>(DownloadState.NotDownloaded)
|
||||
val seriesDownloadState: StateFlow<DownloadState> = _seriesDownloadState
|
||||
|
||||
@@ -111,6 +122,15 @@ class SeriesViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteSmartDownloads(seriesId: UUID) {
|
||||
viewModelScope.launch {
|
||||
mediaDownloadManager.deleteSmartDownloads(seriesId)
|
||||
if (_series.value?.offline == true) {
|
||||
navigationManager.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadSeries(seriesData: Series) {
|
||||
viewModelScope.launch {
|
||||
val mediaCatalogReader = selectedMediaCatalogReader()
|
||||
|
||||
Reference in New Issue
Block a user