From f60aba5a7266ebc5083e193efe709e836fac130d Mon Sep 17 00:00:00 2001 From: Barnabas Balogh Date: Thu, 14 May 2026 12:56:48 +0200 Subject: [PATCH] feat: update media selection logic to handle offline state in view models and DTOs --- .../purefin/navigation/TvRouteEntryBuilder.kt | 2 +- .../ui/screen/episode/TvEpisodeScreen.kt | 6 +-- .../purefin/ui/screen/movie/TvMovieScreen.kt | 4 +- .../ui/screen/series/TvSeriesScreen.kt | 4 +- .../ui/screen/episode/EpisodeScreen.kt | 6 +-- .../purefin/ui/screen/movie/MovieScreen.kt | 4 +- .../purefin/ui/screen/series/SeriesScreen.kt | 14 ++++-- .../series/components/SeriesComponents.kt | 7 +-- .../content/episode/EpisodeScreenViewModel.kt | 47 ++++++++++++------- .../content/movie/MovieScreenViewModel.kt | 27 +++++++---- .../feature/content/series/SeriesViewModel.kt | 38 +++++++++++---- .../feature/downloads/DownloadsViewModel.kt | 6 +-- .../purefin/core/navigation/EpisodeDto.kt | 1 + .../bbara/purefin/core/navigation/MovieDto.kt | 1 + .../purefin/core/navigation/SeriesDto.kt | 1 + .../catalog/OfflineLocalMediaRepository.kt | 2 +- .../data/offline/room/dao/EpisodeDao.kt | 4 +- .../data/offline/room/dao/SeasonDao.kt | 2 +- .../OfflineRoomMediaLocalDataSource.kt | 7 +-- 19 files changed, 111 insertions(+), 72 deletions(-) diff --git a/app-tv/src/main/java/hu/bbara/purefin/navigation/TvRouteEntryBuilder.kt b/app-tv/src/main/java/hu/bbara/purefin/navigation/TvRouteEntryBuilder.kt index 97e2b759..4cf1074e 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/navigation/TvRouteEntryBuilder.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/navigation/TvRouteEntryBuilder.kt @@ -40,7 +40,7 @@ fun EntryProviderScope.tvSeriesSection() { fun EntryProviderScope.tvEpisodeSection() { entry { route -> TvSeriesScreen( - series = SeriesDto(id = route.item.seriesId), + series = SeriesDto(id = route.item.seriesId, offline = route.item.offline), focusedSeasonId = route.item.seasonId, focusedEpisodeId = route.item.id ) diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt index 9371fbc8..743f993a 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/episode/TvEpisodeScreen.kt @@ -37,11 +37,7 @@ fun TvEpisodeScreen( val navigationManager = LocalNavigationManager.current LaunchedEffect(episode) { - viewModel.selectEpisode( - seriesId = episode.seriesId, - seasonId = episode.seasonId, - episodeId = episode.id - ) + viewModel.selectEpisode(episode) } val episode = viewModel.episode.collectAsState() diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt index cc77d23f..933f90b1 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/movie/TvMovieScreen.kt @@ -28,8 +28,8 @@ fun TvMovieScreen( viewModel: MovieScreenViewModel = hiltViewModel(), modifier: Modifier = Modifier ) { - LaunchedEffect(movie.id) { - viewModel.selectMovie(movie.id) + LaunchedEffect(movie) { + viewModel.selectMovie(movie) } val movieItem = viewModel.movie.collectAsState() diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt index 426aa8e3..28a33525 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt @@ -42,8 +42,8 @@ fun TvSeriesScreen( modifier: Modifier = Modifier, viewModel: SeriesViewModel = hiltViewModel() ) { - LaunchedEffect(series.id) { - viewModel.selectSeries(series.id) + LaunchedEffect(series) { + viewModel.selectSeries(series) } val series = viewModel.series.collectAsState() diff --git a/app/src/main/java/hu/bbara/purefin/ui/screen/episode/EpisodeScreen.kt b/app/src/main/java/hu/bbara/purefin/ui/screen/episode/EpisodeScreen.kt index 001d9997..9bebb4a7 100644 --- a/app/src/main/java/hu/bbara/purefin/ui/screen/episode/EpisodeScreen.kt +++ b/app/src/main/java/hu/bbara/purefin/ui/screen/episode/EpisodeScreen.kt @@ -43,11 +43,7 @@ fun EpisodeScreen( val previousRoute = remember(backStack) { backStack.getOrNull(backStack.lastIndex - 1) } LaunchedEffect(episode) { - viewModel.selectEpisode( - seriesId = episode.seriesId, - seasonId = episode.seasonId, - episodeId = episode.id - ) + viewModel.selectEpisode(episode) } val episode = viewModel.episode.collectAsState() diff --git a/app/src/main/java/hu/bbara/purefin/ui/screen/movie/MovieScreen.kt b/app/src/main/java/hu/bbara/purefin/ui/screen/movie/MovieScreen.kt index ad42dd85..c458efe8 100644 --- a/app/src/main/java/hu/bbara/purefin/ui/screen/movie/MovieScreen.kt +++ b/app/src/main/java/hu/bbara/purefin/ui/screen/movie/MovieScreen.kt @@ -35,8 +35,8 @@ fun MovieScreen( viewModel: MovieScreenViewModel = hiltViewModel(), modifier: Modifier = Modifier ) { - LaunchedEffect(movie.id) { - viewModel.selectMovie(movie.id) + LaunchedEffect(movie) { + viewModel.selectMovie(movie) } val movieItem = viewModel.movie.collectAsState() 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 5ecfab8b..3850e6fd 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 @@ -45,13 +45,13 @@ fun SeriesScreen( modifier: Modifier = Modifier, viewModel: SeriesViewModel = hiltViewModel() ) { - LaunchedEffect(series.id) { - viewModel.selectSeries(series.id) + LaunchedEffect(series) { + viewModel.selectSeries(series) } - val series = viewModel.series.collectAsState() + val seriesState = viewModel.series.collectAsState() - val seriesData = series.value + val seriesData = seriesState.value if (seriesData != null && seriesData.seasons.isNotEmpty()) { LaunchedEffect(seriesData) { viewModel.observeSeriesDownloadState(seriesData) @@ -75,6 +75,7 @@ fun SeriesScreen( onLoadSeasonEpisodes = viewModel::loadSeasonEpisodes, onObserveSeasonDownloadState = viewModel::observeSeasonDownloadState, onBack = viewModel::onGoHome, + offline = series.offline, modifier = modifier ) } else { @@ -91,6 +92,7 @@ private fun SeriesScreenInternal( onLoadSeasonEpisodes: (UUID, UUID) -> Unit, onObserveSeasonDownloadState: (List) -> Unit, onBack: () -> Unit, + offline: Boolean, modifier: Modifier = Modifier, ) { val scheme = MaterialTheme.colorScheme @@ -128,6 +130,7 @@ private fun SeriesScreenInternal( seriesDownloadState = seriesDownloadState, selectedSeason = selectedSeason, seasonDownloadState = seasonDownloadState, + offline = offline, onDownloadOptionSelected = { option -> onDownloadOptionSelected(option, selectedSeason) } @@ -188,7 +191,8 @@ private fun SeriesScreenPreview() { onDownloadOptionSelected = { _, _ -> }, onLoadSeasonEpisodes = { _, _ -> }, onObserveSeasonDownloadState = {}, - onBack = {} + onBack = {}, + offline = false, ) } } 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 ef036043..26c323f1 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 @@ -112,6 +112,7 @@ internal fun SeriesActionButtons( seriesDownloadState: DownloadState, selectedSeason: Season, seasonDownloadState: DownloadState, + offline: Boolean, onDownloadOptionSelected: (SeriesDownloadOption) -> Unit, modifier: Modifier = Modifier, ) { @@ -119,8 +120,7 @@ internal fun SeriesActionButtons( val navigationManager = LocalNavigationManager.current val scheme = MaterialTheme.colorScheme var showDownloadDialog by remember { mutableStateOf(false) } - val episodeId = nextUpEpisode?.id - val playAction = remember(nextUpEpisode) { + val playAction = remember(nextUpEpisode, offline) { nextUpEpisode?.let { episode -> { navigationManager.navigate( @@ -128,7 +128,8 @@ internal fun SeriesActionButtons( EpisodeDto( id = episode.id, seasonId = episode.seasonId, - seriesId = episode.seriesId + seriesId = episode.seriesId, + offline = offline, ) ) ) 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 b193ad45..ffea3803 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 @@ -3,14 +3,15 @@ package hu.bbara.purefin.core.feature.content.episode import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import hu.bbara.purefin.core.Offline import hu.bbara.purefin.core.data.LocalMediaRepository import hu.bbara.purefin.core.download.DownloadState import hu.bbara.purefin.core.download.MediaDownloadController +import hu.bbara.purefin.core.navigation.EpisodeDto import hu.bbara.purefin.core.navigation.NavigationManager import hu.bbara.purefin.core.navigation.Route import hu.bbara.purefin.core.navigation.SeriesDto import hu.bbara.purefin.model.Episode -import java.util.UUID import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -25,28 +26,32 @@ import javax.inject.Inject @HiltViewModel class EpisodeScreenViewModel @Inject constructor( - private val mediaCatalogReader: LocalMediaRepository, + private val defaultMediaCatalogReader: LocalMediaRepository, + @param:Offline private val offlineMediaCatalogReader: LocalMediaRepository, private val navigationManager: NavigationManager, private val mediaDownloadManager: MediaDownloadController, ): ViewModel() { - private val _episodeId = MutableStateFlow(null) - private val _seriesId = MutableStateFlow(null) + private val _episode = MutableStateFlow(null) @OptIn(ExperimentalCoroutinesApi::class) - val episode: StateFlow = _episodeId - .flatMapLatest { episodeId -> - if (episodeId == null) flowOf(null) else mediaCatalogReader.getEpisode(episodeId) + val episode: StateFlow = _episode + .flatMapLatest { episode -> + if (episode == null) { + flowOf(null) + } else { + mediaCatalogReader(episode.offline).getEpisode(episode.id) + } } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) @OptIn(ExperimentalCoroutinesApi::class) - val seriesTitle: StateFlow = _seriesId - .flatMapLatest { seriesId -> - if (seriesId == null) { + val seriesTitle: StateFlow = _episode + .flatMapLatest { episode -> + if (episode == null) { flowOf(null) } else { - mediaCatalogReader.getSeries(seriesId).map { it?.name } + mediaCatalogReader(episode.offline).getSeries(episode.seriesId).map { it?.name } } } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) @@ -59,22 +64,25 @@ class EpisodeScreenViewModel @Inject constructor( } fun onSeriesClick() { - val seriesId = _seriesId.value ?: return - navigationManager.navigate(Route.SeriesRoute(SeriesDto(id = seriesId))) + val episode = _episode.value ?: return + navigationManager.navigate( + Route.SeriesRoute( + SeriesDto(id = episode.seriesId, offline = episode.offline) + ) + ) } - fun selectEpisode(seriesId: UUID, seasonId: UUID, episodeId: UUID) { - _episodeId.value = episodeId - _seriesId.value = seriesId + fun selectEpisode(episode: EpisodeDto) { + _episode.value = episode viewModelScope.launch { - mediaDownloadManager.observeDownloadState(episodeId.toString()).collect { + mediaDownloadManager.observeDownloadState(episode.id.toString()).collect { _downloadState.value = it } } } fun onDownloadClick() { - val episodeId = _episodeId.value ?: return + val episodeId = _episode.value?.id ?: return viewModelScope.launch { when (_downloadState.value) { is DownloadState.NotDownloaded, is DownloadState.Failed -> { @@ -87,4 +95,7 @@ class EpisodeScreenViewModel @Inject constructor( } } + private fun mediaCatalogReader(offline: Boolean): LocalMediaRepository { + return if (offline) offlineMediaCatalogReader else defaultMediaCatalogReader + } } 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 13f3c516..706eff72 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 @@ -3,13 +3,14 @@ package hu.bbara.purefin.core.feature.content.movie import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import hu.bbara.purefin.core.Offline import hu.bbara.purefin.core.data.LocalMediaRepository import hu.bbara.purefin.core.download.DownloadState import hu.bbara.purefin.core.download.MediaDownloadController +import hu.bbara.purefin.core.navigation.MovieDto import hu.bbara.purefin.core.navigation.NavigationManager import hu.bbara.purefin.core.navigation.Route import hu.bbara.purefin.model.Movie -import java.util.UUID import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -23,17 +24,22 @@ import javax.inject.Inject @HiltViewModel class MovieScreenViewModel @Inject constructor( - private val mediaCatalogReader: LocalMediaRepository, + private val defaultMediaCatalogReader: LocalMediaRepository, + @param:Offline private val offlineMediaCatalogReader: LocalMediaRepository, private val navigationManager: NavigationManager, private val mediaDownloadManager: MediaDownloadController, ): ViewModel() { - private val _movieId = MutableStateFlow(null) + private val _movie = MutableStateFlow(null) @OptIn(ExperimentalCoroutinesApi::class) - val movie: StateFlow = _movieId - .flatMapLatest { movieId -> - if (movieId == null) flowOf(null) else mediaCatalogReader.getMovie(movieId) + val movie: StateFlow = _movie + .flatMapLatest { movie -> + if (movie == null) { + flowOf(null) + } else { + mediaCatalogReader(movie.offline).getMovie(movie.id) + } } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) @@ -53,10 +59,10 @@ class MovieScreenViewModel @Inject constructor( navigationManager.replaceAll(Route.Home) } - fun selectMovie(movieId: UUID) { - _movieId.value = movieId + fun selectMovie(movie: MovieDto) { + _movie.value = movie viewModelScope.launch { - mediaDownloadManager.observeDownloadState(movieId.toString()).collect { + mediaDownloadManager.observeDownloadState(movie.id.toString()).collect { _downloadState.value = it } } @@ -79,4 +85,7 @@ class MovieScreenViewModel @Inject constructor( } } + private fun mediaCatalogReader(offline: Boolean): LocalMediaRepository { + return if (offline) offlineMediaCatalogReader else defaultMediaCatalogReader + } } 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 ec2e81c1..ed423c92 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 @@ -3,12 +3,14 @@ package hu.bbara.purefin.core.feature.content.series import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import hu.bbara.purefin.core.Offline import hu.bbara.purefin.core.data.LocalMediaRepository import hu.bbara.purefin.core.download.DownloadState import hu.bbara.purefin.core.download.MediaDownloadController import hu.bbara.purefin.core.navigation.EpisodeDto import hu.bbara.purefin.core.navigation.NavigationManager import hu.bbara.purefin.core.navigation.Route +import hu.bbara.purefin.core.navigation.SeriesDto import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Series import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -27,17 +29,22 @@ import javax.inject.Inject @HiltViewModel class SeriesViewModel @Inject constructor( - private val mediaCatalogReader: LocalMediaRepository, + private val defaultMediaCatalogReader: LocalMediaRepository, + @param:Offline private val offlineMediaCatalogReader: LocalMediaRepository, private val navigationManager: NavigationManager, private val mediaDownloadManager: MediaDownloadController, ) : ViewModel() { - private val _seriesId = MutableStateFlow(null) + private val _series = MutableStateFlow(null) @OptIn(ExperimentalCoroutinesApi::class) - val series: StateFlow = _seriesId - .flatMapLatest { seriesId -> - if (seriesId == null) flowOf(null) else mediaCatalogReader.getSeries(seriesId) + val series: StateFlow = _series + .flatMapLatest { series -> + if (series == null) { + flowOf(null) + } else { + mediaCatalogReader(series.offline).getSeries(series.id) + } } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null) @@ -80,12 +87,13 @@ class SeriesViewModel @Inject constructor( fun loadSeasonEpisodes(seriesId: UUID, seasonId: UUID) { viewModelScope.launch { - mediaCatalogReader.loadSeasonEpisodes(seriesId, seasonId) + selectedMediaCatalogReader().loadSeasonEpisodes(seriesId, seasonId) } } fun downloadSeason(seriesId: UUID, seasonId: UUID) { viewModelScope.launch { + val mediaCatalogReader = selectedMediaCatalogReader() mediaCatalogReader.loadSeasonEpisodes(seriesId, seasonId) val episodes = mediaCatalogReader.getSeries(seriesId) .first() @@ -105,6 +113,7 @@ class SeriesViewModel @Inject constructor( fun downloadSeries(seriesData: Series) { viewModelScope.launch { + val mediaCatalogReader = selectedMediaCatalogReader() seriesData.seasons.forEach { season -> mediaCatalogReader.loadSeasonEpisodes(seriesData.id, season.id) } @@ -136,7 +145,8 @@ class SeriesViewModel @Inject constructor( EpisodeDto( id = episodeId, seasonId = seasonId, - seriesId = seriesId + seriesId = seriesId, + offline = _series.value?.offline == true, ) )) } @@ -153,10 +163,18 @@ class SeriesViewModel @Inject constructor( navigationManager.replaceAll(Route.Home) } - fun selectSeries(seriesId: UUID) { - _seriesId.value = seriesId + fun selectSeries(series: SeriesDto) { + _series.value = series viewModelScope.launch { - mediaCatalogReader.loadSeasons(seriesId) + mediaCatalogReader(series.offline).loadSeasons(series.id) } } + + private fun selectedMediaCatalogReader(): LocalMediaRepository { + return mediaCatalogReader(_series.value?.offline == true) + } + + private fun mediaCatalogReader(offline: Boolean): LocalMediaRepository { + return if (offline) offlineMediaCatalogReader else defaultMediaCatalogReader + } } diff --git a/core/src/main/java/hu/bbara/purefin/core/feature/downloads/DownloadsViewModel.kt b/core/src/main/java/hu/bbara/purefin/core/feature/downloads/DownloadsViewModel.kt index 16ece628..38012b41 100644 --- a/core/src/main/java/hu/bbara/purefin/core/feature/downloads/DownloadsViewModel.kt +++ b/core/src/main/java/hu/bbara/purefin/core/feature/downloads/DownloadsViewModel.kt @@ -23,7 +23,7 @@ import javax.inject.Inject @HiltViewModel class DownloadsViewModel @Inject constructor( - @Offline private val offlineCatalogReader: LocalMediaRepository, + @param:Offline private val offlineCatalogReader: LocalMediaRepository, private val navigationManager: NavigationManager, private val downloadManager: MediaDownloadController, ) : ViewModel() { @@ -31,7 +31,7 @@ class DownloadsViewModel @Inject constructor( fun onMovieSelected(movieId: UUID) { navigationManager.navigate( Route.MovieRoute( - MovieDto(id = movieId) + MovieDto(id = movieId, offline = true) )) } @@ -39,7 +39,7 @@ class DownloadsViewModel @Inject constructor( viewModelScope.launch { navigationManager.navigate( Route.SeriesRoute( - SeriesDto(id = seriesId) + SeriesDto(id = seriesId, offline = true) )) } } diff --git a/core/src/main/java/hu/bbara/purefin/core/navigation/EpisodeDto.kt b/core/src/main/java/hu/bbara/purefin/core/navigation/EpisodeDto.kt index f99dd41c..9524b517 100644 --- a/core/src/main/java/hu/bbara/purefin/core/navigation/EpisodeDto.kt +++ b/core/src/main/java/hu/bbara/purefin/core/navigation/EpisodeDto.kt @@ -11,4 +11,5 @@ data class EpisodeDto( val seasonId: UUID, @Serializable(with = UuidSerializer::class) val seriesId: UUID, + val offline: Boolean = false, ) diff --git a/core/src/main/java/hu/bbara/purefin/core/navigation/MovieDto.kt b/core/src/main/java/hu/bbara/purefin/core/navigation/MovieDto.kt index c9b1b693..87fb982e 100644 --- a/core/src/main/java/hu/bbara/purefin/core/navigation/MovieDto.kt +++ b/core/src/main/java/hu/bbara/purefin/core/navigation/MovieDto.kt @@ -7,4 +7,5 @@ import kotlinx.serialization.Serializable data class MovieDto( @Serializable(with = UuidSerializer::class) val id: UUID, + val offline: Boolean = false, ) diff --git a/core/src/main/java/hu/bbara/purefin/core/navigation/SeriesDto.kt b/core/src/main/java/hu/bbara/purefin/core/navigation/SeriesDto.kt index 98f79203..911c5cf5 100644 --- a/core/src/main/java/hu/bbara/purefin/core/navigation/SeriesDto.kt +++ b/core/src/main/java/hu/bbara/purefin/core/navigation/SeriesDto.kt @@ -7,4 +7,5 @@ import kotlinx.serialization.Serializable data class SeriesDto( @Serializable(with = UuidSerializer::class) val id: UUID, + val offline: Boolean = false, ) diff --git a/data/src/main/java/hu/bbara/purefin/data/catalog/OfflineLocalMediaRepository.kt b/data/src/main/java/hu/bbara/purefin/data/catalog/OfflineLocalMediaRepository.kt index 5b995bb1..50357987 100644 --- a/data/src/main/java/hu/bbara/purefin/data/catalog/OfflineLocalMediaRepository.kt +++ b/data/src/main/java/hu/bbara/purefin/data/catalog/OfflineLocalMediaRepository.kt @@ -37,7 +37,7 @@ class OfflineLocalMediaRepository @Inject constructor( } override suspend fun getSeries(id: UUID): Flow { - return series.map { it[id] } + return localDataSource.observeSeriesWithContent(id) } override suspend fun getEpisode(id: UUID): Flow { diff --git a/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/EpisodeDao.kt b/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/EpisodeDao.kt index b3184d3b..ca386537 100644 --- a/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/EpisodeDao.kt +++ b/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/EpisodeDao.kt @@ -15,10 +15,10 @@ interface EpisodeDao { @Upsert suspend fun upsertAll(episodes: List) - @Query("SELECT * FROM episodes WHERE seriesId = :seriesId") + @Query("SELECT * FROM episodes WHERE seriesId = :seriesId ORDER BY seasonIndex ASC, `index` ASC") suspend fun getBySeriesId(seriesId: UUID): List - @Query("SELECT * FROM episodes WHERE seasonId = :seasonId") + @Query("SELECT * FROM episodes WHERE seasonId = :seasonId ORDER BY `index` ASC") suspend fun getBySeasonId(seasonId: UUID): List @Query("SELECT * FROM episodes") diff --git a/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/SeasonDao.kt b/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/SeasonDao.kt index 5a70479f..394bd044 100644 --- a/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/SeasonDao.kt +++ b/data/src/main/java/hu/bbara/purefin/data/offline/room/dao/SeasonDao.kt @@ -14,7 +14,7 @@ interface SeasonDao { @Upsert suspend fun upsertAll(seasons: List) - @Query("SELECT * FROM seasons WHERE seriesId = :seriesId") + @Query("SELECT * FROM seasons WHERE seriesId = :seriesId ORDER BY `index` ASC") suspend fun getBySeriesId(seriesId: UUID): List @Query("SELECT * FROM seasons WHERE id = :id") diff --git a/data/src/main/java/hu/bbara/purefin/data/offline/room/offline/OfflineRoomMediaLocalDataSource.kt b/data/src/main/java/hu/bbara/purefin/data/offline/room/offline/OfflineRoomMediaLocalDataSource.kt index 5a5bd2a2..a406d7d6 100644 --- a/data/src/main/java/hu/bbara/purefin/data/offline/room/offline/OfflineRoomMediaLocalDataSource.kt +++ b/data/src/main/java/hu/bbara/purefin/data/offline/room/offline/OfflineRoomMediaLocalDataSource.kt @@ -43,11 +43,12 @@ class OfflineRoomMediaLocalDataSource( seriesDao.observeWithContent(seriesId).map { relation -> relation?.let { it.series.toDomain( - seasons = it.seasons.map { swe -> + seasons = it.seasons.sortedBy { swe -> swe.season.index }.map { swe -> swe.season.toDomain( - episodes = swe.episodes.map { ep -> ep.toDomain() } + episodes = swe.episodes.sortedBy { ep -> ep.index }.map { ep -> ep.toDomain() } ) - } ) + } + ) } }