Remove local database because it is not being used at this moment of the project.

This commit is contained in:
2026-01-30 15:38:03 +01:00
parent 32d0029379
commit 7cde4b357e
15 changed files with 0 additions and 642 deletions

View File

@@ -73,8 +73,6 @@ dependencies {
implementation(libs.medi3.ui.compose) implementation(libs.medi3.ui.compose)
implementation(libs.androidx.navigation3.runtime) implementation(libs.androidx.navigation3.runtime)
implementation(libs.androidx.navigation3.ui) implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
@@ -83,5 +81,4 @@ dependencies {
debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest) debugImplementation(libs.androidx.compose.ui.test.manifest)
ksp(libs.hilt.compiler) ksp(libs.hilt.compiler)
ksp(libs.androidx.room.compiler)
} }

View File

@@ -1,35 +0,0 @@
package hu.bbara.purefin.data.local.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.entity.EpisodeEntity
import java.util.UUID
@Dao
interface EpisodeDao {
@Upsert
suspend fun upsertEpisode(episode: EpisodeEntity)
@Upsert
suspend fun upsertEpisodes(episodes: List<EpisodeEntity>)
@Query("DELETE FROM episodes WHERE id = :episodeId")
suspend fun deleteEpisode(episodeId: UUID)
@Query("DELETE FROM episodes WHERE seasonId = :seasonId")
suspend fun deleteEpisodesForSeason(seasonId: UUID)
@Query("DELETE FROM episodes WHERE seriesId = :seriesId")
suspend fun deleteEpisodesForSeries(seriesId: UUID)
@Query("SELECT * FROM episodes WHERE id = :episodeId")
suspend fun getEpisodeById(episodeId: UUID): EpisodeEntity?
@Query("SELECT * FROM episodes WHERE seasonId = :seasonId ORDER BY `index` ASC")
suspend fun getEpisodesForSeason(seasonId: UUID): List<EpisodeEntity>
@Query("SELECT * FROM episodes WHERE seriesId = :seriesId ORDER BY seasonId, `index` ASC")
suspend fun getEpisodesForSeries(seriesId: UUID): List<EpisodeEntity>
}

View File

@@ -1,40 +0,0 @@
package hu.bbara.purefin.data.local.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Upsert
import hu.bbara.purefin.data.local.entity.SeasonEntity
import hu.bbara.purefin.data.local.relations.SeasonWithEpisodes
import java.util.UUID
import kotlinx.coroutines.flow.Flow
@Dao
interface SeasonDao {
@Upsert
suspend fun upsertSeason(season: SeasonEntity)
@Upsert
suspend fun upsertSeasons(seasons: List<SeasonEntity>)
@Query("DELETE FROM seasons WHERE id = :seasonId")
suspend fun deleteSeason(seasonId: UUID)
@Query("DELETE FROM seasons WHERE seriesId = :seriesId")
suspend fun deleteSeasonsForSeries(seriesId: UUID)
@Transaction
@Query("SELECT * FROM seasons WHERE id = :seasonId")
suspend fun getSeasonWithEpisodes(seasonId: UUID): SeasonWithEpisodes?
@Query("SELECT * FROM seasons WHERE id = :seasonId")
suspend fun getSeasonById(seasonId: UUID): SeasonEntity?
@Query("SELECT * FROM seasons WHERE seriesId = :seriesId ORDER BY `index` ASC")
suspend fun getSeasonsForSeries(seriesId: UUID): List<SeasonEntity>
@Transaction
@Query("SELECT * FROM seasons WHERE seriesId = :seriesId ORDER BY `index` ASC")
fun observeSeasonsWithEpisodes(seriesId: UUID): Flow<List<SeasonWithEpisodes>>
}

View File

@@ -1,41 +0,0 @@
package hu.bbara.purefin.data.local.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Upsert
import hu.bbara.purefin.data.local.entity.SeriesEntity
import hu.bbara.purefin.data.local.relations.SeriesWithSeasonsAndEpisodes
import java.util.UUID
import kotlinx.coroutines.flow.Flow
@Dao
interface SeriesDao {
@Upsert
suspend fun upsertSeries(series: SeriesEntity)
@Upsert
suspend fun upsertSeries(series: List<SeriesEntity>)
@Query("DELETE FROM series WHERE id = :seriesId")
suspend fun deleteSeries(seriesId: UUID)
@Transaction
@Query("SELECT * FROM series WHERE id = :seriesId")
suspend fun getSeriesWithContent(seriesId: UUID): SeriesWithSeasonsAndEpisodes?
@Transaction
@Query("SELECT * FROM series WHERE id = :seriesId")
fun observeSeriesWithContent(seriesId: UUID): Flow<SeriesWithSeasonsAndEpisodes?>
@Transaction
@Query("SELECT * FROM series")
fun observeAllSeriesWithContent(): Flow<List<SeriesWithSeasonsAndEpisodes>>
@Query("SELECT * FROM series WHERE id = :seriesId")
suspend fun getSeriesById(seriesId: UUID): SeriesEntity?
@Query("SELECT * FROM series")
fun observeSeriesEntities(): Flow<List<SeriesEntity>>
}

View File

@@ -1,26 +0,0 @@
package hu.bbara.purefin.data.local.db
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import hu.bbara.purefin.data.local.dao.EpisodeDao
import hu.bbara.purefin.data.local.dao.SeasonDao
import hu.bbara.purefin.data.local.dao.SeriesDao
import hu.bbara.purefin.data.local.entity.EpisodeEntity
import hu.bbara.purefin.data.local.entity.SeasonEntity
import hu.bbara.purefin.data.local.entity.SeriesEntity
@Database(
entities = [SeriesEntity::class, SeasonEntity::class, EpisodeEntity::class],
version = 1,
exportSchema = false
)
@TypeConverters(PurefinTypeConverters::class)
abstract class PurefinDatabase : RoomDatabase() {
abstract fun seriesDao(): SeriesDao
abstract fun seasonDao(): SeasonDao
abstract fun episodeDao(): EpisodeDao
}

View File

@@ -1,52 +0,0 @@
package hu.bbara.purefin.data.local.db
import androidx.room.TypeConverter
import hu.bbara.purefin.data.local.entity.EpisodeCastMemberEntity
import java.util.UUID
import org.json.JSONArray
import org.json.JSONObject
class PurefinTypeConverters {
@TypeConverter
fun fromUuid(value: UUID?): String? = value?.toString()
@TypeConverter
fun toUuid(value: String?): UUID? = value?.let(UUID::fromString)
@TypeConverter
fun fromCastMembers(value: List<EpisodeCastMemberEntity>?): String? {
if (value.isNullOrEmpty()) return null
val jsonArray = JSONArray()
value.forEach { member ->
jsonArray.put(
JSONObject().apply {
put("name", member.name)
put("role", member.role)
put("imageUrl", member.imageUrl)
}
)
}
return jsonArray.toString()
}
@TypeConverter
fun toCastMembers(value: String?): List<EpisodeCastMemberEntity> {
if (value.isNullOrBlank()) return emptyList()
val jsonArray = JSONArray(value)
val members = mutableListOf<EpisodeCastMemberEntity>()
for (index in 0 until jsonArray.length()) {
val jsonObject = jsonArray.optJSONObject(index) ?: continue
val imageUrl = when {
jsonObject.has("imageUrl") && !jsonObject.isNull("imageUrl") -> jsonObject.optString("imageUrl")
else -> null
}
members += EpisodeCastMemberEntity(
name = jsonObject.optString("name"),
role = jsonObject.optString("role"),
imageUrl = imageUrl?.ifBlank { null }
)
}
return members
}
}

View File

@@ -1,50 +0,0 @@
package hu.bbara.purefin.data.local.di
import android.content.Context
import androidx.room.Room
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.local.dao.EpisodeDao
import hu.bbara.purefin.data.local.dao.SeasonDao
import hu.bbara.purefin.data.local.dao.SeriesDao
import hu.bbara.purefin.data.local.db.PurefinDatabase
import hu.bbara.purefin.data.local.repository.LocalMediaRepository
import hu.bbara.purefin.data.local.repository.RoomLocalMediaRepository
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun provideDatabase(
@ApplicationContext context: Context
): PurefinDatabase {
return Room.databaseBuilder(
context,
PurefinDatabase::class.java,
"purefin.db"
).build()
}
@Provides
fun provideSeriesDao(database: PurefinDatabase): SeriesDao = database.seriesDao()
@Provides
fun provideSeasonDao(database: PurefinDatabase): SeasonDao = database.seasonDao()
@Provides
fun provideEpisodeDao(database: PurefinDatabase): EpisodeDao = database.episodeDao()
@Provides
@Singleton
fun provideLocalMediaRepository(
seriesDao: SeriesDao,
seasonDao: SeasonDao,
episodeDao: EpisodeDao
): LocalMediaRepository = RoomLocalMediaRepository(seriesDao, seasonDao, episodeDao)
}

View File

@@ -1,48 +0,0 @@
package hu.bbara.purefin.data.local.entity
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import java.util.UUID
@Entity(
tableName = "episodes",
foreignKeys = [
ForeignKey(
entity = SeriesEntity::class,
parentColumns = ["id"],
childColumns = ["seriesId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = SeasonEntity::class,
parentColumns = ["id"],
childColumns = ["seasonId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
],
indices = [Index(value = ["seriesId"]), Index(value = ["seasonId"])]
)
data class EpisodeEntity(
@PrimaryKey val id: UUID,
val seriesId: UUID,
val seasonId: UUID,
val title: String,
val index: Int,
val releaseDate: String,
val rating: String,
val runtime: String,
val format: String,
val synopsis: String,
val heroImageUrl: String,
val cast: List<EpisodeCastMemberEntity>
)
data class EpisodeCastMemberEntity(
val name: String,
val role: String,
val imageUrl: String?
)

View File

@@ -1,28 +0,0 @@
package hu.bbara.purefin.data.local.entity
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import java.util.UUID
@Entity(
tableName = "seasons",
foreignKeys = [
ForeignKey(
entity = SeriesEntity::class,
parentColumns = ["id"],
childColumns = ["seriesId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
],
indices = [Index(value = ["seriesId"])]
)
data class SeasonEntity(
@PrimaryKey val id: UUID,
val seriesId: UUID,
val name: String,
val index: Int,
val episodeCount: Int
)

View File

@@ -1,15 +0,0 @@
package hu.bbara.purefin.data.local.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.UUID
@Entity(tableName = "series")
data class SeriesEntity(
@PrimaryKey val id: UUID,
val name: String,
val synopsis: String,
val year: String,
val heroImageUrl: String,
val seasonCount: Int
)

View File

@@ -1,15 +0,0 @@
package hu.bbara.purefin.data.local.relations
import androidx.room.Embedded
import androidx.room.Relation
import hu.bbara.purefin.data.local.entity.EpisodeEntity
import hu.bbara.purefin.data.local.entity.SeasonEntity
data class SeasonWithEpisodes(
@Embedded val season: SeasonEntity,
@Relation(
parentColumn = "id",
entityColumn = "seasonId"
)
val episodes: List<EpisodeEntity>
)

View File

@@ -1,16 +0,0 @@
package hu.bbara.purefin.data.local.relations
import androidx.room.Embedded
import androidx.room.Relation
import hu.bbara.purefin.data.local.entity.SeasonEntity
import hu.bbara.purefin.data.local.entity.SeriesEntity
data class SeriesWithSeasonsAndEpisodes(
@Embedded val series: SeriesEntity,
@Relation(
entity = SeasonEntity::class,
parentColumn = "id",
entityColumn = "seriesId"
)
val seasons: List<SeasonWithEpisodes>
)

View File

@@ -1,40 +0,0 @@
package hu.bbara.purefin.data.local.repository
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import java.util.UUID
import kotlinx.coroutines.flow.Flow
interface LocalMediaRepository {
suspend fun upsertSeries(series: Series)
suspend fun upsertSeries(seriesList: List<Series>)
suspend fun getSeries(seriesId: UUID, includeContent: Boolean = true): Series?
fun observeSeries(seriesId: UUID): Flow<Series?>
fun observeAllSeries(): Flow<List<Series>>
suspend fun deleteSeries(seriesId: UUID)
suspend fun upsertSeason(season: Season)
suspend fun upsertSeasons(seasons: List<Season>)
suspend fun getSeason(seasonId: UUID, includeEpisodes: Boolean = true): Season?
fun observeSeasons(seriesId: UUID): Flow<List<Season>>
suspend fun deleteSeason(seasonId: UUID)
suspend fun upsertEpisode(episode: Episode)
suspend fun upsertEpisodes(episodes: List<Episode>)
suspend fun getEpisode(episodeId: UUID): Episode?
suspend fun deleteEpisode(episodeId: UUID)
}

View File

@@ -1,229 +0,0 @@
package hu.bbara.purefin.data.local.repository
import hu.bbara.purefin.app.content.episode.CastMember
import hu.bbara.purefin.data.local.dao.EpisodeDao
import hu.bbara.purefin.data.local.dao.SeasonDao
import hu.bbara.purefin.data.local.dao.SeriesDao
import hu.bbara.purefin.data.local.entity.EpisodeCastMemberEntity
import hu.bbara.purefin.data.local.entity.EpisodeEntity
import hu.bbara.purefin.data.local.entity.SeasonEntity
import hu.bbara.purefin.data.local.entity.SeriesEntity
import hu.bbara.purefin.data.local.relations.SeasonWithEpisodes
import hu.bbara.purefin.data.local.relations.SeriesWithSeasonsAndEpisodes
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import java.util.UUID
import javax.inject.Inject
class RoomLocalMediaRepository @Inject constructor(
private val seriesDao: SeriesDao,
private val seasonDao: SeasonDao,
private val episodeDao: EpisodeDao
) : LocalMediaRepository {
override suspend fun upsertSeries(series: Series) {
withContext(Dispatchers.IO) {
seriesDao.upsertSeries(series.toEntity())
upsertSeasonsInternal(series.seasons)
}
}
override suspend fun upsertSeries(seriesList: List<Series>) {
if (seriesList.isEmpty()) return
withContext(Dispatchers.IO) {
seriesDao.upsertSeries(seriesList.map { it.toEntity() })
val seasons = seriesList.flatMap { it.seasons }
upsertSeasonsInternal(seasons)
}
}
override suspend fun getSeries(seriesId: UUID, includeContent: Boolean): Series? {
return withContext(Dispatchers.IO) {
if (includeContent) {
seriesDao.getSeriesWithContent(seriesId)?.toDomain()
} else {
seriesDao.getSeriesById(seriesId)?.toDomain(emptyList())
}
}
}
override fun observeSeries(seriesId: UUID): Flow<Series?> {
return seriesDao.observeSeriesWithContent(seriesId).map { relation ->
relation?.toDomain()
}
}
override fun observeAllSeries(): Flow<List<Series>> {
return seriesDao.observeAllSeriesWithContent().map { relations ->
relations.map { it.toDomain() }
}
}
override suspend fun deleteSeries(seriesId: UUID) {
withContext(Dispatchers.IO) {
seriesDao.deleteSeries(seriesId)
}
}
override suspend fun upsertSeason(season: Season) {
withContext(Dispatchers.IO) {
upsertSeasonsInternal(listOf(season))
}
}
override suspend fun upsertSeasons(seasons: List<Season>) {
if (seasons.isEmpty()) return
withContext(Dispatchers.IO) {
upsertSeasonsInternal(seasons)
}
}
override suspend fun getSeason(seasonId: UUID, includeEpisodes: Boolean): Season? {
return withContext(Dispatchers.IO) {
if (includeEpisodes) {
seasonDao.getSeasonWithEpisodes(seasonId)?.toDomain()
} else {
seasonDao.getSeasonById(seasonId)?.toDomain(emptyList())
}
}
}
override fun observeSeasons(seriesId: UUID): Flow<List<Season>> {
return seasonDao.observeSeasonsWithEpisodes(seriesId).map { relations ->
relations.map { it.toDomain() }
}
}
override suspend fun deleteSeason(seasonId: UUID) {
withContext(Dispatchers.IO) {
seasonDao.deleteSeason(seasonId)
}
}
override suspend fun upsertEpisode(episode: Episode) {
withContext(Dispatchers.IO) {
episodeDao.upsertEpisode(episode.toEntity())
}
}
override suspend fun upsertEpisodes(episodes: List<Episode>) {
if (episodes.isEmpty()) return
withContext(Dispatchers.IO) {
episodeDao.upsertEpisodes(episodes.map { it.toEntity() })
}
}
override suspend fun getEpisode(episodeId: UUID): Episode? {
return withContext(Dispatchers.IO) {
episodeDao.getEpisodeById(episodeId)?.toDomain()
}
}
override suspend fun deleteEpisode(episodeId: UUID) {
withContext(Dispatchers.IO) {
episodeDao.deleteEpisode(episodeId)
}
}
private suspend fun upsertSeasonsInternal(seasons: List<Season>) {
if (seasons.isEmpty()) return
seasonDao.upsertSeasons(seasons.map { it.toEntity() })
val episodes = seasons.flatMap { it.episodes }
if (episodes.isNotEmpty()) {
episodeDao.upsertEpisodes(episodes.map { it.toEntity() })
}
}
}
private fun SeriesEntity.toDomain(seasons: List<Season>): Series = Series(
id = id,
name = name,
synopsis = synopsis,
year = year,
heroImageUrl = heroImageUrl,
seasonCount = seasonCount,
seasons = seasons,
//TODO check if it is needed
cast = emptyList()
)
private fun SeasonEntity.toDomain(episodes: List<Episode>): Season = Season(
id = id,
seriesId = seriesId,
name = name,
index = index,
episodeCount = episodeCount,
episodes = episodes
)
private fun EpisodeEntity.toDomain(): Episode = Episode(
id = id,
seriesId = seriesId,
seasonId = seasonId,
title = title,
index = index,
releaseDate = releaseDate,
rating = rating,
runtime = runtime,
format = format,
synopsis = synopsis,
heroImageUrl = heroImageUrl,
progress = 13.0,
watched = false,
cast = emptyList()
)
private fun SeriesWithSeasonsAndEpisodes.toDomain(): Series =
series.toDomain(seasons.map { it.toDomain() })
private fun SeasonWithEpisodes.toDomain(): Season =
season.toDomain(episodes.map { it.toDomain() })
private fun Series.toEntity(): SeriesEntity = SeriesEntity(
id = id,
name = name,
synopsis = synopsis,
year = year,
heroImageUrl = heroImageUrl,
seasonCount = seasonCount
)
private fun Season.toEntity(): SeasonEntity = SeasonEntity(
id = id,
seriesId = seriesId,
name = name,
index = index,
episodeCount = episodeCount
)
private fun Episode.toEntity(): EpisodeEntity = EpisodeEntity(
id = id,
seriesId = seriesId,
seasonId = seasonId,
title = title,
index = index,
releaseDate = releaseDate,
rating = rating,
runtime = runtime,
format = format,
synopsis = synopsis,
heroImageUrl = heroImageUrl,
cast = emptyList()
)
private fun EpisodeCastMemberEntity.toDomain(): CastMember = CastMember(
name = name,
role = role,
imageUrl = imageUrl
)
private fun CastMember.toEntity(): EpisodeCastMemberEntity = EpisodeCastMemberEntity(
name = name,
role = role,
imageUrl = imageUrl
)

View File

@@ -19,7 +19,6 @@ foundation = "1.10.1"
coil = "3.3.0" coil = "3.3.0"
media3 = "1.9.0" media3 = "1.9.0"
nav3Core = "1.0.0" nav3Core = "1.0.0"
room = "2.6.1"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -55,9 +54,6 @@ medi3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media
medi3-ui-compose = { group = "androidx.media3", name = "media3-ui-compose-material3", version.ref = "media3"} medi3-ui-compose = { group = "androidx.media3", name = "media3-ui-compose-material3", version.ref = "media3"}
androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" } androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" }
androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" } androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[plugins] [plugins]