From a0dbef3dc15ef36ccffb0ecb4171da16276630d9 Mon Sep 17 00:00:00 2001 From: Barnabas Balogh Date: Wed, 18 Feb 2026 17:56:29 +0100 Subject: [PATCH] feat: Added library to the database scheme and to the MediaRepository. LibraryViewModel now uses it. --- .../purefin/app/library/LibraryViewModel.kt | 57 ++++++------------- .../purefin/data/ActiveMediaRepository.kt | 5 ++ .../purefin/data/InMemoryMediaRepository.kt | 4 ++ .../hu/bbara/purefin/data/MediaRepository.kt | 2 + .../purefin/data/OfflineMediaRepository.kt | 4 ++ .../purefin/data/local/room/LibraryEntity.kt | 13 +++++ .../purefin/data/local/room/MediaDatabase.kt | 6 +- .../data/local/room/MediaDatabaseModule.kt | 19 +++++-- .../purefin/data/local/room/MovieEntity.kt | 14 ++++- .../data/local/room/OfflineMediaDatabase.kt | 5 +- .../room/OfflineRoomMediaLocalDataSource.kt | 45 ++++++++++++++- .../local/room/RoomMediaLocalDataSource.kt | 47 ++++++++++++++- .../purefin/data/local/room/RoomRelations.kt | 14 +++++ .../purefin/data/local/room/SeriesEntity.kt | 14 ++++- .../purefin/data/local/room/dao/LibraryDao.kt | 29 ++++++++++ 15 files changed, 227 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/hu/bbara/purefin/data/local/room/LibraryEntity.kt create mode 100644 app/src/main/java/hu/bbara/purefin/data/local/room/dao/LibraryDao.kt diff --git a/app/src/main/java/hu/bbara/purefin/app/library/LibraryViewModel.kt b/app/src/main/java/hu/bbara/purefin/app/library/LibraryViewModel.kt index 7533593..cb6d362 100644 --- a/app/src/main/java/hu/bbara/purefin/app/library/LibraryViewModel.kt +++ b/app/src/main/java/hu/bbara/purefin/app/library/LibraryViewModel.kt @@ -17,44 +17,38 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.jellyfin.sdk.model.UUID import org.jellyfin.sdk.model.api.BaseItemKind +import org.jellyfin.sdk.model.api.CollectionType import org.jellyfin.sdk.model.api.ImageType import javax.inject.Inject +import kotlin.collections.emptyList @HiltViewModel class LibraryViewModel @Inject constructor( private val mediaRepository: MediaRepository, - private val userSessionRepository: UserSessionRepository, - private val jellyfinApiClient: JellyfinApiClient, private val navigationManager: NavigationManager ) : ViewModel() { - private val _url = userSessionRepository.serverUrl.stateIn( - scope = viewModelScope, - started = SharingStarted.Eagerly, - initialValue = "" - ) + private val selectedLibrary = MutableStateFlow(null) - private val _libraryItems = MutableStateFlow>(emptyList()) - - val contents: StateFlow> = combine( - _libraryItems, - mediaRepository.movies, - mediaRepository.series - ) { items, moviesMap, seriesMap -> - items.mapNotNull { media -> - when (media) { - is Media.MovieMedia -> moviesMap[media.movieId]?.let { - PosterItem(type = BaseItemKind.MOVIE, movie = it) - } - is Media.SeriesMedia -> seriesMap[media.seriesId]?.let { - PosterItem(type = BaseItemKind.SERIES, series = it) - } - else -> null + val contents: StateFlow> = combine(selectedLibrary, mediaRepository.libraries) { + libraryId, libraries -> + if (libraryId == null) { + return@combine emptyList() + } + val library = libraries.find { it.id == libraryId } ?: return@combine emptyList() + when (library.type) { + CollectionType.TVSHOWS -> library.series!!.map { series -> + PosterItem(type = BaseItemKind.SERIES, series = series) } + CollectionType.MOVIES -> library.movies!!.map { movie -> + PosterItem(type = BaseItemKind.MOVIE, movie = movie) + } + else -> emptyList() } }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList()) @@ -86,22 +80,7 @@ class LibraryViewModel @Inject constructor( fun selectLibrary(libraryId: UUID) { viewModelScope.launch { - val libraryItems = jellyfinApiClient.getLibraryContent(libraryId) - _libraryItems.value = libraryItems.map { - when (it.type) { - BaseItemKind.MOVIE -> Media.MovieMedia(movieId = it.id) - BaseItemKind.SERIES -> Media.SeriesMedia(seriesId = it.id) - else -> throw UnsupportedOperationException("Unsupported item type: ${it.type}") - } - } + selectedLibrary.value = libraryId } } - - fun getImageUrl(itemId: UUID, type: ImageType): String { - return JellyfinImageHelper.toImageUrl( - url = _url.value, - itemId = itemId, - type = type - ) - } } diff --git a/app/src/main/java/hu/bbara/purefin/data/ActiveMediaRepository.kt b/app/src/main/java/hu/bbara/purefin/data/ActiveMediaRepository.kt index a30d28e..45ca20b 100644 --- a/app/src/main/java/hu/bbara/purefin/data/ActiveMediaRepository.kt +++ b/app/src/main/java/hu/bbara/purefin/data/ActiveMediaRepository.kt @@ -3,6 +3,7 @@ package hu.bbara.purefin.data import hu.bbara.purefin.data.local.room.OfflineRepository import hu.bbara.purefin.data.local.room.OnlineRepository import hu.bbara.purefin.data.model.Episode +import hu.bbara.purefin.data.model.Library import hu.bbara.purefin.data.model.Media import hu.bbara.purefin.data.model.Movie import hu.bbara.purefin.data.model.Series @@ -44,6 +45,10 @@ class ActiveMediaRepository @Inject constructor( .stateIn(scope, SharingStarted.Eagerly, onlineRepository) // Delegate all MediaRepository interface methods to the active repository + override val libraries: StateFlow> = + activeRepository.flatMapLatest { it.libraries } + .stateIn(scope, SharingStarted.Eagerly, emptyList()) + override val movies: StateFlow> = activeRepository.flatMapLatest { it.movies } .stateIn(scope, SharingStarted.Eagerly, emptyMap()) diff --git a/app/src/main/java/hu/bbara/purefin/data/InMemoryMediaRepository.kt b/app/src/main/java/hu/bbara/purefin/data/InMemoryMediaRepository.kt index 326d450..dc48be5 100644 --- a/app/src/main/java/hu/bbara/purefin/data/InMemoryMediaRepository.kt +++ b/app/src/main/java/hu/bbara/purefin/data/InMemoryMediaRepository.kt @@ -47,6 +47,8 @@ class InMemoryMediaRepository @Inject constructor( private val _state: MutableStateFlow = MutableStateFlow(MediaRepositoryState.Loading) override val state: StateFlow = _state.asStateFlow() + override val libraries: StateFlow> = localDataSource.librariesFlow + .stateIn(scope, SharingStarted.Eagerly, emptyList()) override val movies: StateFlow> = localDataSource.moviesFlow .stateIn(scope, SharingStarted.Eagerly, emptyMap()) @@ -108,6 +110,8 @@ class InMemoryMediaRepository @Inject constructor( val emptyLibraries = filteredLibraries.map { it.toLibrary() } + localDataSource.saveLibraries(emptyLibraries) + val filledLibraries = emptyLibraries.map { library -> return@map loadLibrary(library) } diff --git a/app/src/main/java/hu/bbara/purefin/data/MediaRepository.kt b/app/src/main/java/hu/bbara/purefin/data/MediaRepository.kt index 82b8b84..489820d 100644 --- a/app/src/main/java/hu/bbara/purefin/data/MediaRepository.kt +++ b/app/src/main/java/hu/bbara/purefin/data/MediaRepository.kt @@ -1,6 +1,7 @@ package hu.bbara.purefin.data import hu.bbara.purefin.data.model.Episode +import hu.bbara.purefin.data.model.Library import hu.bbara.purefin.data.model.Media import hu.bbara.purefin.data.model.Movie import hu.bbara.purefin.data.model.Series @@ -10,6 +11,7 @@ import java.util.UUID interface MediaRepository { + val libraries: StateFlow> val movies: StateFlow> val series: StateFlow> val episodes: StateFlow> diff --git a/app/src/main/java/hu/bbara/purefin/data/OfflineMediaRepository.kt b/app/src/main/java/hu/bbara/purefin/data/OfflineMediaRepository.kt index b677004..b6a8e61 100644 --- a/app/src/main/java/hu/bbara/purefin/data/OfflineMediaRepository.kt +++ b/app/src/main/java/hu/bbara/purefin/data/OfflineMediaRepository.kt @@ -3,6 +3,7 @@ package hu.bbara.purefin.data import hu.bbara.purefin.data.local.room.OfflineDatabase import hu.bbara.purefin.data.local.room.OfflineRoomMediaLocalDataSource import hu.bbara.purefin.data.model.Episode +import hu.bbara.purefin.data.model.Library import hu.bbara.purefin.data.model.Media import hu.bbara.purefin.data.model.Movie import hu.bbara.purefin.data.model.Series @@ -34,6 +35,9 @@ class OfflineMediaRepository @Inject constructor( private val _state: MutableStateFlow = MutableStateFlow(MediaRepositoryState.Ready) override val state: StateFlow = _state.asStateFlow() + override val libraries: StateFlow> = localDataSource.librariesFlow + .stateIn(scope, SharingStarted.Eagerly, emptyList()) + override val movies: StateFlow> = localDataSource.moviesFlow .stateIn(scope, SharingStarted.Eagerly, emptyMap()) diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/LibraryEntity.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/LibraryEntity.kt new file mode 100644 index 0000000..4216f69 --- /dev/null +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/LibraryEntity.kt @@ -0,0 +1,13 @@ +package hu.bbara.purefin.data.local.room + +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.util.UUID + +@Entity(tableName = "library") +data class LibraryEntity ( + @PrimaryKey + val id: UUID, + val name: String, + val type: String, +) \ No newline at end of file diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabase.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabase.kt index a83e9f5..131b558 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabase.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabase.kt @@ -8,16 +8,17 @@ import hu.bbara.purefin.data.local.room.dao.EpisodeDao import hu.bbara.purefin.data.local.room.dao.MovieDao import hu.bbara.purefin.data.local.room.dao.SeasonDao import hu.bbara.purefin.data.local.room.dao.SeriesDao - +import hu.bbara.purefin.data.local.room.dao.LibraryDao @Database( entities = [ MovieEntity::class, SeriesEntity::class, SeasonEntity::class, EpisodeEntity::class, + LibraryEntity::class, CastMemberEntity::class ], - version = 1, + version = 3, exportSchema = false ) @TypeConverters(UuidConverters::class) @@ -26,5 +27,6 @@ abstract class MediaDatabase : RoomDatabase() { abstract fun seriesDao(): SeriesDao abstract fun seasonDao(): SeasonDao abstract fun episodeDao(): EpisodeDao + abstract fun libraryDao(): LibraryDao abstract fun castMemberDao(): CastMemberDao } diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabaseModule.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabaseModule.kt index d11fa53..c3565a5 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabaseModule.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/MediaDatabaseModule.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import hu.bbara.purefin.data.local.room.dao.CastMemberDao import hu.bbara.purefin.data.local.room.dao.EpisodeDao +import hu.bbara.purefin.data.local.room.dao.LibraryDao import hu.bbara.purefin.data.local.room.dao.MovieDao import hu.bbara.purefin.data.local.room.dao.SeasonDao import hu.bbara.purefin.data.local.room.dao.SeriesDao @@ -47,6 +48,10 @@ object MediaDatabaseModule { @OnlineDatabase fun provideOnlineCastMemberDao(@OnlineDatabase db: MediaDatabase) = db.castMemberDao() + @Provides + @OnlineDatabase + fun provideOnlineLibraryDao(@OnlineDatabase db: MediaDatabase) = db.libraryDao() + // Offline Database and DAOs @Provides @Singleton @@ -76,6 +81,10 @@ object MediaDatabaseModule { @OfflineDatabase fun provideOfflineCastMemberDao(@OfflineDatabase db: OfflineMediaDatabase) = db.castMemberDao() + @Provides + @OfflineDatabase + fun provideOfflineLibraryDao(@OfflineDatabase db: OfflineMediaDatabase) = db.libraryDao() + // Data Sources @Provides @Singleton @@ -86,9 +95,10 @@ object MediaDatabaseModule { @OnlineDatabase seriesDao: SeriesDao, @OnlineDatabase seasonDao: SeasonDao, @OnlineDatabase episodeDao: EpisodeDao, - @OnlineDatabase castMemberDao: CastMemberDao + @OnlineDatabase castMemberDao: CastMemberDao, + @OnlineDatabase libraryDao: LibraryDao ): RoomMediaLocalDataSource = RoomMediaLocalDataSource( - database, movieDao, seriesDao, seasonDao, episodeDao, castMemberDao + database, movieDao, seriesDao, seasonDao, episodeDao, castMemberDao, libraryDao ) @Provides @@ -100,9 +110,10 @@ object MediaDatabaseModule { @OfflineDatabase seriesDao: SeriesDao, @OfflineDatabase seasonDao: SeasonDao, @OfflineDatabase episodeDao: EpisodeDao, - @OfflineDatabase castMemberDao: CastMemberDao + @OfflineDatabase castMemberDao: CastMemberDao, + @OfflineDatabase libraryDao: LibraryDao ): OfflineRoomMediaLocalDataSource = OfflineRoomMediaLocalDataSource( - database, movieDao, seriesDao, seasonDao, episodeDao, castMemberDao + database, movieDao, seriesDao, seasonDao, episodeDao, castMemberDao, libraryDao ) // Default (unqualified) data source for backward compatibility diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/MovieEntity.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/MovieEntity.kt index 9acb008..0cd005d 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/MovieEntity.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/MovieEntity.kt @@ -1,10 +1,22 @@ package hu.bbara.purefin.data.local.room import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Index import androidx.room.PrimaryKey import java.util.UUID -@Entity(tableName = "movies") +@Entity( + tableName = "movies", + foreignKeys = [ + ForeignKey( + entity = LibraryEntity::class, + parentColumns = ["id"], + childColumns = ["libraryId"], + ), + ], + indices = [Index("libraryId")] +) data class MovieEntity( @PrimaryKey val id: UUID, val libraryId: UUID, diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineMediaDatabase.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineMediaDatabase.kt index cb6198b..c6c8e8e 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineMediaDatabase.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineMediaDatabase.kt @@ -8,6 +8,7 @@ import hu.bbara.purefin.data.local.room.dao.EpisodeDao import hu.bbara.purefin.data.local.room.dao.MovieDao import hu.bbara.purefin.data.local.room.dao.SeasonDao import hu.bbara.purefin.data.local.room.dao.SeriesDao +import hu.bbara.purefin.data.local.room.dao.LibraryDao @Database( entities = [ @@ -15,9 +16,10 @@ import hu.bbara.purefin.data.local.room.dao.SeriesDao SeriesEntity::class, SeasonEntity::class, EpisodeEntity::class, + LibraryEntity::class, CastMemberEntity::class ], - version = 1, + version = 3, exportSchema = false ) @TypeConverters(UuidConverters::class) @@ -26,5 +28,6 @@ abstract class OfflineMediaDatabase : RoomDatabase() { abstract fun seriesDao(): SeriesDao abstract fun seasonDao(): SeasonDao abstract fun episodeDao(): EpisodeDao + abstract fun libraryDao(): LibraryDao abstract fun castMemberDao(): CastMemberDao } diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineRoomMediaLocalDataSource.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineRoomMediaLocalDataSource.kt index 3d3ebb7..bfc80e9 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineRoomMediaLocalDataSource.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/OfflineRoomMediaLocalDataSource.kt @@ -3,16 +3,19 @@ package hu.bbara.purefin.data.local.room import androidx.room.withTransaction import hu.bbara.purefin.data.local.room.dao.CastMemberDao import hu.bbara.purefin.data.local.room.dao.EpisodeDao +import hu.bbara.purefin.data.local.room.dao.LibraryDao import hu.bbara.purefin.data.local.room.dao.MovieDao import hu.bbara.purefin.data.local.room.dao.SeasonDao import hu.bbara.purefin.data.local.room.dao.SeriesDao import hu.bbara.purefin.data.model.CastMember import hu.bbara.purefin.data.model.Episode +import hu.bbara.purefin.data.model.Library import hu.bbara.purefin.data.model.Movie import hu.bbara.purefin.data.model.Season import hu.bbara.purefin.data.model.Series import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import org.jellyfin.sdk.model.api.CollectionType import java.util.UUID import javax.inject.Inject import javax.inject.Singleton @@ -24,10 +27,21 @@ class OfflineRoomMediaLocalDataSource( private val seriesDao: SeriesDao, private val seasonDao: SeasonDao, private val episodeDao: EpisodeDao, - private val castMemberDao: CastMemberDao + private val castMemberDao: CastMemberDao, + private val libraryDao: LibraryDao ) { // Lightweight Flows for list screens (home, library) + val librariesFlow: Flow> = libraryDao.observeAllWithContent() + .map { relation -> + relation.map { + it.library.toDomain( + movies = it.movies.map { e -> e.toDomain(cast = emptyList()) }, + series = it.series.map { e -> e.toDomain(seasons = emptyList(), cast = emptyList()) } + ) + } + } + val moviesFlow: Flow> = movieDao.observeAll() .map { entities -> entities.associate { it.id to it.toDomain(cast = emptyList()) } } @@ -54,6 +68,13 @@ class OfflineRoomMediaLocalDataSource( } } + suspend fun saveLibraries(libraries: List) { + database.withTransaction { + libraryDao.deleteAll() + libraryDao.upsertAll(libraries.map { it.toEntity() }) + } + } + suspend fun saveMovies(movies: List) { database.withTransaction { movieDao.upsertAll(movies.map { it.toEntity() }) @@ -184,6 +205,28 @@ class OfflineRoomMediaLocalDataSource( } } + private fun Library.toEntity() = LibraryEntity( + id = id, + name = name, + type = when (type) { + CollectionType.MOVIES -> "MOVIES" + CollectionType.TVSHOWS -> "TVSHOWS" + else -> throw UnsupportedOperationException("Unsupported library type: $type") + } + ) + + private fun LibraryEntity.toDomain(series: List, movies: List) = Library( + id = id, + name = name, + type = when (type) { + "MOVIES" -> CollectionType.MOVIES + "TVSHOWS" -> CollectionType.TVSHOWS + else -> throw UnsupportedOperationException("Unsupported library type: $type") + }, + movies = if (type == "MOVIES") movies else null, + series = if (type == "TVSHOWS") series else null, + ) + private fun Movie.toEntity() = MovieEntity( id = id, libraryId = libraryId, diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/RoomMediaLocalDataSource.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/RoomMediaLocalDataSource.kt index 54b1289..976ddd1 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/RoomMediaLocalDataSource.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/RoomMediaLocalDataSource.kt @@ -3,19 +3,22 @@ package hu.bbara.purefin.data.local.room import androidx.room.withTransaction import hu.bbara.purefin.data.local.room.dao.CastMemberDao import hu.bbara.purefin.data.local.room.dao.EpisodeDao +import hu.bbara.purefin.data.local.room.dao.LibraryDao import hu.bbara.purefin.data.local.room.dao.MovieDao import hu.bbara.purefin.data.local.room.dao.SeasonDao import hu.bbara.purefin.data.local.room.dao.SeriesDao import hu.bbara.purefin.data.model.CastMember import hu.bbara.purefin.data.model.Episode +import hu.bbara.purefin.data.model.Library import hu.bbara.purefin.data.model.Movie import hu.bbara.purefin.data.model.Season import hu.bbara.purefin.data.model.Series import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import org.jellyfin.sdk.model.api.CollectionType import java.util.UUID -import javax.inject.Inject import javax.inject.Singleton +import kotlin.collections.map @Singleton class RoomMediaLocalDataSource( @@ -24,10 +27,21 @@ class RoomMediaLocalDataSource( private val seriesDao: SeriesDao, private val seasonDao: SeasonDao, private val episodeDao: EpisodeDao, - private val castMemberDao: CastMemberDao + private val castMemberDao: CastMemberDao, + private val libraryDao: LibraryDao ) { // Lightweight Flows for list screens (home, library) + val librariesFlow: Flow> = libraryDao.observeAllWithContent() + .map { relation -> + relation.map { libraryEntity -> + libraryEntity.library.toDomain( + movies = libraryEntity.movies.map { it.toDomain(listOf()) }, + series = libraryEntity.series.map { it.toDomain(listOf(), listOf()) } + ) + } + } + val moviesFlow: Flow> = movieDao.observeAll() .map { entities -> entities.associate { it.id to it.toDomain(cast = emptyList()) } } @@ -54,6 +68,13 @@ class RoomMediaLocalDataSource( } } + suspend fun saveLibraries(libraries: List) { + database.withTransaction { + libraryDao.deleteAll() + libraryDao.upsertAll(libraries.map { it.toEntity() }) + } + } + suspend fun saveMovies(movies: List) { database.withTransaction { movieDao.upsertAll(movies.map { it.toEntity() }) @@ -184,6 +205,28 @@ class RoomMediaLocalDataSource( } } + private fun Library.toEntity() = LibraryEntity( + id = id, + name = name, + type = when (type) { + CollectionType.MOVIES -> "MOVIES" + CollectionType.TVSHOWS -> "TVSHOWS" + else -> throw UnsupportedOperationException("Unsupported library type: $type") + } + ) + + private fun LibraryEntity.toDomain(series: List, movies: List) = Library( + id = id, + name = name, + type = when (type) { + "MOVIES" -> CollectionType.MOVIES + "TVSHOWS" -> CollectionType.TVSHOWS + else -> throw UnsupportedOperationException("Unsupported library type: $type") + }, + movies = if (type == "MOVIES") movies else null, + series = if (type == "TVSHOWS") series else null, + ) + private fun Movie.toEntity() = MovieEntity( id = id, libraryId = libraryId, diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/RoomRelations.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/RoomRelations.kt index 783e14d..2cd99df 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/RoomRelations.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/RoomRelations.kt @@ -21,3 +21,17 @@ data class SeriesWithSeasonsAndEpisodes( ) val seasons: List ) + +data class LibraryWithContent( + @Embedded val library: LibraryEntity, + @Relation( + parentColumn = "id", + entityColumn = "libraryId" + ) + val series: List, + @Relation( + parentColumn = "id", + entityColumn = "libraryId" + ) + val movies: List +) diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/SeriesEntity.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/SeriesEntity.kt index 8419aae..cf363d6 100644 --- a/app/src/main/java/hu/bbara/purefin/data/local/room/SeriesEntity.kt +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/SeriesEntity.kt @@ -1,10 +1,22 @@ package hu.bbara.purefin.data.local.room import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Index import androidx.room.PrimaryKey import java.util.UUID -@Entity(tableName = "series") +@Entity( + tableName = "series", + foreignKeys = [ + ForeignKey( + entity = LibraryEntity::class, + parentColumns = ["id"], + childColumns = ["libraryId"], + ), + ], + indices = [Index("libraryId")] +) data class SeriesEntity( @PrimaryKey val id: UUID, val libraryId: UUID, diff --git a/app/src/main/java/hu/bbara/purefin/data/local/room/dao/LibraryDao.kt b/app/src/main/java/hu/bbara/purefin/data/local/room/dao/LibraryDao.kt new file mode 100644 index 0000000..0ca53d1 --- /dev/null +++ b/app/src/main/java/hu/bbara/purefin/data/local/room/dao/LibraryDao.kt @@ -0,0 +1,29 @@ +package hu.bbara.purefin.data.local.room.dao + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Upsert +import hu.bbara.purefin.data.local.room.LibraryEntity +import hu.bbara.purefin.data.local.room.LibraryWithContent +import kotlinx.coroutines.flow.Flow + +@Dao +interface LibraryDao { + @Upsert + suspend fun upsert(library: LibraryEntity) + + @Upsert + suspend fun upsertAll(libraries: List) + + @Query("SELECT * FROM library") + fun observeAll(): Flow> + + @Query("SELECT * FROM library") + fun observeAllWithContent(): Flow> + + @Query("SELECT * FROM library") + suspend fun getAll(): List + + @Query("DELETE FROM library") + suspend fun deleteAll() +}