diff --git a/app/src/main/java/hu/bbara/purefin/ui/screen/series/SeriesScreen.kt b/app/src/main/java/hu/bbara/purefin/ui/screen/series/SeriesScreen.kt index 3850e6fd..dcf3997f 100644 --- a/app/src/main/java/hu/bbara/purefin/ui/screen/series/SeriesScreen.kt +++ b/app/src/main/java/hu/bbara/purefin/ui/screen/series/SeriesScreen.kt @@ -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) -> 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 = {}, diff --git a/app/src/main/java/hu/bbara/purefin/ui/screen/series/components/SeriesComponents.kt b/app/src/main/java/hu/bbara/purefin/ui/screen/series/components/SeriesComponents.kt index 26c323f1..f53a96a1 100644 --- a/app/src/main/java/hu/bbara/purefin/ui/screen/series/components/SeriesComponents.kt +++ b/app/src/main/java/hu/bbara/purefin/ui/screen/series/components/SeriesComponents.kt @@ -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,8 +226,19 @@ private fun DownloadOptionsDialog( } }, dismissButton = { - TextButton(onClick = { onDownloadOptionSelected(SeriesDownloadOption.SMART) }) { - Text("Smart Download") + 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") + } } } ) diff --git a/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadController.kt b/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadController.kt index 13aa3d9b..2530a6c6 100644 --- a/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadController.kt +++ b/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadController.kt @@ -13,5 +13,7 @@ interface MediaDownloadController { suspend fun downloadEpisodes(episodeIds: List) suspend fun cancelEpisodeDownload(episodeId: UUID) suspend fun enableSmartDownload(seriesId: UUID) + suspend fun deleteSmartDownloads(seriesId: UUID) + fun isSmartDownloadEnabled(seriesId: UUID): Flow suspend fun syncSmartDownloads() } diff --git a/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadManager.kt b/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadManager.kt index 784fb201..d1d734e4 100644 --- a/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadManager.kt +++ b/core/src/main/java/hu/bbara/purefin/core/download/MediaDownloadManager.kt @@ -206,11 +206,16 @@ class MediaDownloadManager @Inject constructor( syncSmartDownloadsForSeries(seriesId) } - suspend fun disableSmartDownload(seriesId: UUID) { - smartDownloadStore.disable(seriesId) + 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 = smartDownloadStore.observe(seriesId) + override fun isSmartDownloadEnabled(seriesId: UUID): Flow = smartDownloadStore.observe(seriesId) override suspend fun syncSmartDownloads() { withContext(Dispatchers.IO) { diff --git a/core/src/main/java/hu/bbara/purefin/core/feature/content/episode/EpisodeScreenViewModel.kt b/core/src/main/java/hu/bbara/purefin/core/feature/content/episode/EpisodeScreenViewModel.kt index ffea3803..12c5a545 100644 --- a/core/src/main/java/hu/bbara/purefin/core/feature/content/episode/EpisodeScreenViewModel.kt +++ b/core/src/main/java/hu/bbara/purefin/core/feature/content/episode/EpisodeScreenViewModel.kt @@ -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() + } + } } } } diff --git a/core/src/main/java/hu/bbara/purefin/core/feature/content/movie/MovieScreenViewModel.kt b/core/src/main/java/hu/bbara/purefin/core/feature/content/movie/MovieScreenViewModel.kt index 706eff72..a9176cf7 100644 --- a/core/src/main/java/hu/bbara/purefin/core/feature/content/movie/MovieScreenViewModel.kt +++ b/core/src/main/java/hu/bbara/purefin/core/feature/content/movie/MovieScreenViewModel.kt @@ -80,6 +80,9 @@ class MovieScreenViewModel @Inject constructor( } is DownloadState.Downloaded -> { mediaDownloadManager.cancelDownload(movieId) + if (_movie.value?.offline == true) { + navigationManager.pop() + } } } } diff --git a/core/src/main/java/hu/bbara/purefin/core/feature/content/series/SeriesViewModel.kt b/core/src/main/java/hu/bbara/purefin/core/feature/content/series/SeriesViewModel.kt index ed423c92..90cfcc03 100644 --- a/core/src/main/java/hu/bbara/purefin/core/feature/content/series/SeriesViewModel.kt +++ b/core/src/main/java/hu/bbara/purefin/core/feature/content/series/SeriesViewModel.kt @@ -48,6 +48,17 @@ class SeriesViewModel @Inject constructor( } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) + @OptIn(ExperimentalCoroutinesApi::class) + val isSmartDownloadEnabled: StateFlow = _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.NotDownloaded) val seriesDownloadState: StateFlow = _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()