mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
refactor(offline): rename OfflineCatalogStore to OfflineMediaManager and consolidate into repository
- Rename interface OfflineCatalogStore → OfflineMediaManager for clarity - Merge RoomOfflineCatalogStore functionality into OfflineLocalMediaRepository - Remove RoomOfflineCatalogStore; update DI binding and consumers
This commit is contained in:
@@ -6,7 +6,7 @@ import hu.bbara.purefin.model.Season
|
|||||||
import hu.bbara.purefin.model.Series
|
import hu.bbara.purefin.model.Series
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
interface OfflineCatalogStore {
|
interface OfflineMediaManager {
|
||||||
suspend fun saveMovies(movies: List<Movie>)
|
suspend fun saveMovies(movies: List<Movie>)
|
||||||
suspend fun saveSeries(series: List<Series>)
|
suspend fun saveSeries(series: List<Series>)
|
||||||
suspend fun saveSeason(season: Season)
|
suspend fun saveSeason(season: Season)
|
||||||
@@ -10,7 +10,7 @@ import androidx.media3.exoplayer.offline.DownloadManager
|
|||||||
import androidx.media3.exoplayer.offline.DownloadRequest
|
import androidx.media3.exoplayer.offline.DownloadRequest
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import hu.bbara.purefin.core.data.DownloadMediaSourceResolver
|
import hu.bbara.purefin.core.data.DownloadMediaSourceResolver
|
||||||
import hu.bbara.purefin.core.data.OfflineCatalogStore
|
import hu.bbara.purefin.core.data.OfflineMediaManager
|
||||||
import hu.bbara.purefin.core.data.SmartDownloadStore
|
import hu.bbara.purefin.core.data.SmartDownloadStore
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -36,7 +36,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val downloadManager: DownloadManager,
|
private val downloadManager: DownloadManager,
|
||||||
private val downloadMediaSourceResolver: DownloadMediaSourceResolver,
|
private val downloadMediaSourceResolver: DownloadMediaSourceResolver,
|
||||||
private val offlineCatalogStore: OfflineCatalogStore,
|
private val offlineMediaManager: OfflineMediaManager,
|
||||||
private val smartDownloadStore: SmartDownloadStore,
|
private val smartDownloadStore: SmartDownloadStore,
|
||||||
) : MediaDownloadController {
|
) : MediaDownloadController {
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
return@withContext
|
return@withContext
|
||||||
}
|
}
|
||||||
|
|
||||||
offlineCatalogStore.saveMovies(listOf(source.movie))
|
offlineMediaManager.saveMovies(listOf(source.movie))
|
||||||
|
|
||||||
Timber.tag(TAG).d("Starting download for '${source.movie.title}' from: ${source.playbackUrl}")
|
Timber.tag(TAG).d("Starting download for '${source.movie.title}' from: ${source.playbackUrl}")
|
||||||
val request = buildDownloadRequest(
|
val request = buildDownloadRequest(
|
||||||
@@ -147,7 +147,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
PurefinDownloadService.sendRemoveDownload(context, movieId.toString())
|
PurefinDownloadService.sendRemoveDownload(context, movieId.toString())
|
||||||
try {
|
try {
|
||||||
offlineCatalogStore.deleteMovie(movieId)
|
offlineMediaManager.deleteMovie(movieId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.tag(TAG).e(e, "Failed to remove movie from offline DB")
|
Timber.tag(TAG).e(e, "Failed to remove movie from offline DB")
|
||||||
}
|
}
|
||||||
@@ -162,15 +162,15 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
return@withContext
|
return@withContext
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offlineCatalogStore.getSeriesBasic(source.series.id) == null) {
|
if (offlineMediaManager.getSeriesBasic(source.series.id) == null) {
|
||||||
offlineCatalogStore.saveSeries(listOf(source.series))
|
offlineMediaManager.saveSeries(listOf(source.series))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offlineCatalogStore.getSeason(source.season.id) == null) {
|
if (offlineMediaManager.getSeason(source.season.id) == null) {
|
||||||
offlineCatalogStore.saveSeason(source.season)
|
offlineMediaManager.saveSeason(source.season)
|
||||||
}
|
}
|
||||||
|
|
||||||
offlineCatalogStore.saveEpisode(source.episode)
|
offlineMediaManager.saveEpisode(source.episode)
|
||||||
|
|
||||||
Timber.tag(TAG).d("Starting download for episode '${source.episode.title}' from: ${source.playbackUrl}")
|
Timber.tag(TAG).d("Starting download for episode '${source.episode.title}' from: ${source.playbackUrl}")
|
||||||
val request = buildDownloadRequest(
|
val request = buildDownloadRequest(
|
||||||
@@ -200,7 +200,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
PurefinDownloadService.sendRemoveDownload(context, episodeId.toString())
|
PurefinDownloadService.sendRemoveDownload(context, episodeId.toString())
|
||||||
try {
|
try {
|
||||||
offlineCatalogStore.deleteEpisodeAndCleanup(episodeId)
|
offlineMediaManager.deleteEpisodeAndCleanup(episodeId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.tag(TAG).e(e, "Failed to remove episode from offline DB")
|
Timber.tag(TAG).e(e, "Failed to remove episode from offline DB")
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
override suspend fun deleteSmartDownloads(seriesId: UUID) {
|
override suspend fun deleteSmartDownloads(seriesId: UUID) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
smartDownloadStore.disable(seriesId)
|
smartDownloadStore.disable(seriesId)
|
||||||
offlineCatalogStore.getEpisodesBySeries(seriesId).forEach { episode ->
|
offlineMediaManager.getEpisodesBySeries(seriesId).forEach { episode ->
|
||||||
cancelEpisodeDownload(episode.id)
|
cancelEpisodeDownload(episode.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ class MediaDownloadManager @Inject constructor(
|
|||||||
private suspend fun syncSmartDownloadsForSeries(seriesId: UUID) {
|
private suspend fun syncSmartDownloadsForSeries(seriesId: UUID) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
// 1. Get currently downloaded episodes for this series
|
// 1. Get currently downloaded episodes for this series
|
||||||
val downloadedEpisodes = offlineCatalogStore.getEpisodesBySeries(seriesId)
|
val downloadedEpisodes = offlineMediaManager.getEpisodesBySeries(seriesId)
|
||||||
|
|
||||||
// 2. Check watched status from server and delete watched downloads
|
// 2. Check watched status from server and delete watched downloads
|
||||||
val unwatchedDownloaded = mutableListOf<UUID>()
|
val unwatchedDownloaded = mutableListOf<UUID>()
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package hu.bbara.purefin.data.catalog
|
package hu.bbara.purefin.data.catalog
|
||||||
|
|
||||||
import hu.bbara.purefin.core.data.LocalMediaRepository
|
import hu.bbara.purefin.core.data.LocalMediaRepository
|
||||||
|
import hu.bbara.purefin.core.data.OfflineMediaManager
|
||||||
import hu.bbara.purefin.data.offline.room.offline.OfflineRoomMediaLocalDataSource
|
import hu.bbara.purefin.data.offline.room.offline.OfflineRoomMediaLocalDataSource
|
||||||
import hu.bbara.purefin.model.Episode
|
import hu.bbara.purefin.model.Episode
|
||||||
import hu.bbara.purefin.model.Movie
|
import hu.bbara.purefin.model.Movie
|
||||||
|
import hu.bbara.purefin.model.Season
|
||||||
import hu.bbara.purefin.model.Series
|
import hu.bbara.purefin.model.Series
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -20,7 +22,7 @@ import javax.inject.Singleton
|
|||||||
@Singleton
|
@Singleton
|
||||||
class OfflineLocalMediaRepository @Inject constructor(
|
class OfflineLocalMediaRepository @Inject constructor(
|
||||||
private val localDataSource: OfflineRoomMediaLocalDataSource,
|
private val localDataSource: OfflineRoomMediaLocalDataSource,
|
||||||
) : LocalMediaRepository {
|
) : LocalMediaRepository, OfflineMediaManager {
|
||||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||||
|
|
||||||
override val movies: StateFlow<Map<UUID, Movie>> = localDataSource.moviesFlow
|
override val movies: StateFlow<Map<UUID, Movie>> = localDataSource.moviesFlow
|
||||||
@@ -68,4 +70,40 @@ class OfflineLocalMediaRepository @Inject constructor(
|
|||||||
override suspend fun markAsWatched(mediaId: UUID, watched: Boolean) {
|
override suspend fun markAsWatched(mediaId: UUID, watched: Boolean) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun saveMovies(movies: List<Movie>) {
|
||||||
|
localDataSource.saveMovies(movies)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveSeries(series: List<Series>) {
|
||||||
|
localDataSource.saveSeries(series)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveSeason(season: Season) {
|
||||||
|
localDataSource.saveSeason(season)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveEpisode(episode: Episode) {
|
||||||
|
localDataSource.saveEpisode(episode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getSeriesBasic(seriesId: UUID): Series? {
|
||||||
|
return localDataSource.getSeriesBasic(seriesId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getSeason(seasonId: UUID): Season? {
|
||||||
|
return localDataSource.getSeason(seasonId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteMovie(movieId: UUID) {
|
||||||
|
localDataSource.deleteMovie(movieId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteEpisodeAndCleanup(episodeId: UUID) {
|
||||||
|
localDataSource.deleteEpisodeAndCleanup(episodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getEpisodesBySeries(seriesId: UUID): List<Episode> {
|
||||||
|
return localDataSource.getEpisodesBySeries(seriesId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ import dagger.Binds
|
|||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import hu.bbara.purefin.core.data.OfflineCatalogStore
|
import hu.bbara.purefin.core.data.OfflineMediaManager
|
||||||
import hu.bbara.purefin.core.data.SmartDownloadStore
|
import hu.bbara.purefin.core.data.SmartDownloadStore
|
||||||
|
import hu.bbara.purefin.data.catalog.OfflineLocalMediaRepository
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
abstract class OfflineBindingsModule {
|
abstract class OfflineBindingsModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindOfflineCatalogStore(impl: RoomOfflineCatalogStore): OfflineCatalogStore
|
abstract fun bindOfflineMediaManager(impl: OfflineLocalMediaRepository): OfflineMediaManager
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSmartDownloadStore(impl: RoomSmartDownloadStore): SmartDownloadStore
|
abstract fun bindSmartDownloadStore(impl: RoomSmartDownloadStore): SmartDownloadStore
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package hu.bbara.purefin.data.offline
|
|
||||||
|
|
||||||
import hu.bbara.purefin.core.data.OfflineCatalogStore
|
|
||||||
import hu.bbara.purefin.data.offline.room.offline.OfflineRoomMediaLocalDataSource
|
|
||||||
import hu.bbara.purefin.model.Episode
|
|
||||||
import hu.bbara.purefin.model.Movie
|
|
||||||
import hu.bbara.purefin.model.Season
|
|
||||||
import hu.bbara.purefin.model.Series
|
|
||||||
import java.util.UUID
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class RoomOfflineCatalogStore @Inject constructor(
|
|
||||||
private val localDataSource: OfflineRoomMediaLocalDataSource,
|
|
||||||
) : OfflineCatalogStore {
|
|
||||||
override suspend fun saveMovies(movies: List<Movie>) {
|
|
||||||
localDataSource.saveMovies(movies)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun saveSeries(series: List<Series>) {
|
|
||||||
localDataSource.saveSeries(series)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun saveSeason(season: Season) {
|
|
||||||
localDataSource.saveSeason(season)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun saveEpisode(episode: Episode) {
|
|
||||||
localDataSource.saveEpisode(episode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getSeriesBasic(seriesId: UUID): Series? {
|
|
||||||
return localDataSource.getSeriesBasic(seriesId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getSeason(seasonId: UUID): Season? {
|
|
||||||
return localDataSource.getSeason(seasonId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun deleteMovie(movieId: UUID) {
|
|
||||||
localDataSource.deleteMovie(movieId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun deleteEpisodeAndCleanup(episodeId: UUID) {
|
|
||||||
localDataSource.deleteEpisodeAndCleanup(episodeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getEpisodesBySeries(seriesId: UUID): List<Episode> {
|
|
||||||
return localDataSource.getEpisodesBySeries(seriesId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user