Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,17 @@ import de.entikore.composedex.data.local.converter.TypesConverter
import de.entikore.composedex.data.local.datasource.GenerationLocalDataSource
import de.entikore.composedex.data.local.datasource.PokemonLocalDataSource
import de.entikore.composedex.data.local.entity.generation.GenerationEntity
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonWithSpeciesTypesAndVarieties
import de.entikore.composedex.data.remote.model.generation.toEntity
import de.entikore.composedex.data.remote.model.toEntity
import de.entikore.sharedtestcode.GEN_II_FILE
import de.entikore.sharedtestcode.GEN_I_FILE
import de.entikore.sharedtestcode.GEN_VI_FILE
import de.entikore.sharedtestcode.POKEMON_GLOOM_NAME
import de.entikore.sharedtestcode.POKEMON_ODDISH_NAME
import de.entikore.sharedtestcode.POKEMON_VILEPLUME_NAME
import de.entikore.sharedtestcode.TestModelFactory.Companion.getGenerationListRemote
import de.entikore.sharedtestcode.TestModelFactory.Companion.getGenerationRemote
import de.entikore.sharedtestcode.TestModelFactory.Companion.getPokemonInfoRemote
import de.entikore.sharedtestcode.TestModelFactory.Companion.getTestModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.test.runTest
import org.junit.After
Expand Down Expand Up @@ -75,15 +71,11 @@ class GenerationLocalDataSourceTest: LocalDataSourceTest() {
.addTypeConverter(TypesConverter(moshi))
.build()
pokemonLocalDataSource = PokemonLocalDataSource(
pokemonDao = database.pokemonDao(),
speciesDao = database.speciesDao(),
varietyDao = database.varietyDao(),
typeDao = database.typeDao(),
database = database,
dispatcher = mainCoroutineRule.getDispatcher()
)
localDataSource = GenerationLocalDataSource(
pokemonLocalDataSource = pokemonLocalDataSource,
generationDao = database.generationDao(),
database = database,
dispatcher = mainCoroutineRule.getDispatcher()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@ class PokemonLocalDataSourceTest: LocalDataSourceTest() {
.addTypeConverter(TypesConverter(moshi))
.build()
localDataSource = PokemonLocalDataSource(
pokemonDao = database.pokemonDao(),
speciesDao = database.speciesDao(),
varietyDao = database.varietyDao(),
typeDao = database.typeDao(),
database = database,
dispatcher = mainCoroutineRule.getDispatcher()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,11 @@ class TypeLocalDataSourceTest: LocalDataSourceTest() {
.addTypeConverter(TypesConverter(moshi))
.build()
pokemonLocalDataSource = PokemonLocalDataSource(
pokemonDao = database.pokemonDao(),
speciesDao = database.speciesDao(),
varietyDao = database.varietyDao(),
typeDao = database.typeDao(),
database = database,
dispatcher = mainCoroutineRule.getDispatcher()
)
localDataSource = TypeLocalDataSource(
pokemonLocalDataSource = pokemonLocalDataSource,
typeDao = database.typeDao(),
database = database,
dispatcher = mainCoroutineRule.getDispatcher()
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 Entikore
* Copyright 2025 Entikore
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@ package de.entikore.composedex.data.local

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.Transaction
import androidx.room.TypeConverters
import de.entikore.composedex.data.local.converter.ChainConverter
import de.entikore.composedex.data.local.converter.StatsConverter
Expand All @@ -33,6 +34,7 @@ import de.entikore.composedex.data.local.entity.pokemon.PokemonEntity
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonSpeciesCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonTypeCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonVarietyCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonWithSpeciesTypesAndVarieties
import de.entikore.composedex.data.local.entity.species.SpeciesEntity
import de.entikore.composedex.data.local.entity.type.TypeEntity
import de.entikore.composedex.data.local.entity.type.TypeOverviewEntity
Expand Down Expand Up @@ -78,6 +80,87 @@ abstract class ComposeDexDatabase : RoomDatabase(), LocalStorage {
this.clearAllTables()
}

@Transaction
suspend fun insertPokemonWithSpeciesTypesAndVarieties(
pokemon: PokemonEntity,
species: SpeciesEntity,
types: List<TypeEntity>,
varieties: List<VarietyEntity>
) {
varieties.forEach { variety ->
varietyDao().insert(variety)
pokemonDao().insertVarietyCrossRef(
PokemonVarietyCrossRef(
pokemon.pokemonId,
variety.varietyName
)
)
}

types.forEach { type ->
typeDao().insert(type)
pokemonDao().insertTypeCrossRef(
PokemonTypeCrossRef(
pokemon.pokemonId,
type.typeId
)
)
}

speciesDao().insert(species)
pokemonDao().insertSpeciesCrossRef(
PokemonSpeciesCrossRef(
pokemon.pokemonId,
species.speciesId
)
)

pokemonDao().insert(pokemon)
}

@Transaction
suspend fun insertPokemonAndAssociateWithType(
typeId: Int,
fullPokemon: PokemonWithSpeciesTypesAndVarieties,
) {
insertPokemonWithSpeciesTypesAndVarieties(
fullPokemon.pokemon,
fullPokemon.species,
fullPokemon.types,
fullPokemon.varieties
)
typeDao().insertPokemonCrossRef(
TypePokemonCrossRef(
typeId,
fullPokemon.pokemon.pokemonId
)
)
}

@Transaction
suspend fun insertPokemonAndAssociateWithGeneration(
generation: GenerationEntity,
fullPokemon: PokemonWithSpeciesTypesAndVarieties
) {
val generationDao = generationDao()

generationDao.insert(generation)

insertPokemonWithSpeciesTypesAndVarieties(
fullPokemon.pokemon,
fullPokemon.species,
fullPokemon.types,
fullPokemon.varieties
)

generationDao.insertPokemonCrossRef(
GenerationPokemonCrossRef(
generation.generationId,
fullPokemon.pokemon.pokemonId
)
)
}

companion object {
const val DATABASE_NAME = "composedex_db"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 Entikore
* Copyright 2025 Entikore
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ class FavouriteLocalDataSource(
) {
suspend fun updateIsFavourite(pokemonId: Int, isFavourite: Boolean) =
withContext(dispatcher) {
return@withContext pokemonDao.updateFavourite(FavouriteUpdate(pokemonId, isFavourite))
pokemonDao.updateFavourite(FavouriteUpdate(pokemonId, isFavourite))
}

fun getAllFavourites(): Flow<List<PokemonWithSpeciesTypesAndVarieties>> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/
package de.entikore.composedex.data.local.datasource

import de.entikore.composedex.data.local.ComposeDexDatabase
import de.entikore.composedex.data.local.dao.GenerationDao
import de.entikore.composedex.data.local.entity.generation.GenerationEntity
import de.entikore.composedex.data.local.entity.generation.GenerationOverviewEntity
import de.entikore.composedex.data.local.entity.generation.relation.GenerationPokemonCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonWithSpeciesTypesAndVarieties
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
Expand All @@ -29,10 +29,10 @@ import kotlinx.coroutines.withContext
* Local data source for [GenerationEntity] instances and their associated [PokemonWithSpeciesTypesAndVarieties].
*/
class GenerationLocalDataSource(
private val pokemonLocalDataSource: PokemonLocalDataSource,
private val generationDao: GenerationDao,
private val database: ComposeDexDatabase,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
) {
private val generationDao: GenerationDao = database.generationDao()

suspend fun insertGenerationOverview(generationOverviewEntity: GenerationOverviewEntity) =
withContext(dispatcher) { generationDao.insertOverview(generationOverviewEntity) }
Expand All @@ -42,19 +42,14 @@ class GenerationLocalDataSource(

suspend fun insertPokemonForGeneration(
generation: GenerationEntity,
pokemon: PokemonWithSpeciesTypesAndVarieties
) {
fullPokemon: PokemonWithSpeciesTypesAndVarieties
) =
withContext(dispatcher) {
insertGeneration(generation)
pokemonLocalDataSource.insertPokemonWithSpeciesTypesAndVarieties(pokemon)
generationDao.insertPokemonCrossRef(
GenerationPokemonCrossRef(
generation.generationId,
pokemon.pokemon.pokemonId
)
database.insertPokemonAndAssociateWithGeneration(
generation,
fullPokemon
)
}
}

fun getGenerationOverview(): Flow<GenerationOverviewEntity?> = generationDao.getOverview()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@
*/
package de.entikore.composedex.data.local.datasource

import de.entikore.composedex.data.local.ComposeDexDatabase
import de.entikore.composedex.data.local.dao.PokemonDao
import de.entikore.composedex.data.local.dao.SpeciesDao
import de.entikore.composedex.data.local.dao.TypeDao
import de.entikore.composedex.data.local.dao.VarietyDao
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonSpeciesCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonTypeCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonVarietyCrossRef
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonWithSpeciesTypesAndVarieties
import de.entikore.composedex.data.local.entity.pokemon.update.ArtworkUpdate
import de.entikore.composedex.data.local.entity.pokemon.update.CryUpdate
Expand All @@ -36,42 +32,22 @@ import kotlinx.coroutines.withContext
* Local data source for [PokemonWithSpeciesTypesAndVarieties] instances.
*/
class PokemonLocalDataSource(
private val pokemonDao: PokemonDao,
private val speciesDao: SpeciesDao,
private val varietyDao: VarietyDao,
private val typeDao: TypeDao,
private val database: ComposeDexDatabase,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
) {
private val pokemonDao: PokemonDao = database.pokemonDao()
private val varietyDao: VarietyDao = database.varietyDao()

suspend fun insertPokemonWithSpeciesTypesAndVarieties(
pokemonWithSpeciesTypesAndVarieties: PokemonWithSpeciesTypesAndVarieties
) =
withContext(dispatcher) {
for (variety in pokemonWithSpeciesTypesAndVarieties.varieties) {
varietyDao.insert(variety)
pokemonDao.insertVarietyCrossRef(
PokemonVarietyCrossRef(
pokemonWithSpeciesTypesAndVarieties.pokemon.pokemonId,
variety.varietyName
)
)
}
for (type in pokemonWithSpeciesTypesAndVarieties.types) {
typeDao.insert(type)
pokemonDao.insertTypeCrossRef(
PokemonTypeCrossRef(
pokemonWithSpeciesTypesAndVarieties.pokemon.pokemonId,
type.typeId
)
)
}
speciesDao.insert(pokemonWithSpeciesTypesAndVarieties.species)
pokemonDao.insertSpeciesCrossRef(
PokemonSpeciesCrossRef(
pokemonWithSpeciesTypesAndVarieties.pokemon.pokemonId,
pokemonWithSpeciesTypesAndVarieties.species.speciesId
)
database.insertPokemonWithSpeciesTypesAndVarieties(
pokemonWithSpeciesTypesAndVarieties.pokemon,
pokemonWithSpeciesTypesAndVarieties.species,
pokemonWithSpeciesTypesAndVarieties.types,
pokemonWithSpeciesTypesAndVarieties.varieties
)
pokemonDao.insert(pokemonWithSpeciesTypesAndVarieties.pokemon)
}

suspend fun updatePokemonArtwork(pokemonId: Int, artworkPath: String) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
*/
package de.entikore.composedex.data.local.datasource

import de.entikore.composedex.data.local.ComposeDexDatabase
import de.entikore.composedex.data.local.dao.TypeDao
import de.entikore.composedex.data.local.entity.pokemon.relation.PokemonWithSpeciesTypesAndVarieties
import de.entikore.composedex.data.local.entity.type.TypeEntity
import de.entikore.composedex.data.local.entity.type.TypeOverviewEntity
import de.entikore.composedex.data.local.entity.type.relation.TypePokemonCrossRef
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
Expand All @@ -29,10 +29,11 @@ import kotlinx.coroutines.withContext
* Local data source for [TypeEntity] instances and their associated [PokemonWithSpeciesTypesAndVarieties].
*/
class TypeLocalDataSource(
private val pokemonLocalDataSource: PokemonLocalDataSource,
private val typeDao: TypeDao,
private val database: ComposeDexDatabase,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
) {
private val typeDao: TypeDao = database.typeDao()

suspend fun insertTypeOverview(typeOverviewEntity: TypeOverviewEntity) =
withContext(dispatcher) { typeDao.insertOverview(typeOverviewEntity) }

Expand All @@ -41,18 +42,14 @@ class TypeLocalDataSource(

suspend fun insertPokemonForType(
type: TypeEntity,
pokemon: PokemonWithSpeciesTypesAndVarieties
) {
fullPokemon: PokemonWithSpeciesTypesAndVarieties
) =
withContext(dispatcher) {
pokemonLocalDataSource.insertPokemonWithSpeciesTypesAndVarieties(pokemon)
typeDao.insertPokemonCrossRef(
TypePokemonCrossRef(
type.typeId,
pokemon.pokemon.pokemonId
)
database.insertPokemonAndAssociateWithType(
type.typeId,
fullPokemon
)
}
}

fun getTypeOverview(): Flow<TypeOverviewEntity?> = typeDao.getOverview()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,9 @@ object LocalModule {

@Provides
fun providePokemonLocalDataSource(
pokemonDao: PokemonDao,
speciesDao: SpeciesDao,
varietyDao: VarietyDao,
typeDao: TypeDao
database: ComposeDexDatabase
): PokemonLocalDataSource =
PokemonLocalDataSource(pokemonDao, speciesDao, varietyDao, typeDao)
PokemonLocalDataSource(database)

@Provides
fun provideFavouriteLocalDataSource(pokemonDao: PokemonDao): FavouriteLocalDataSource =
Expand All @@ -107,14 +104,12 @@ object LocalModule {

@Provides
fun provideTypeLocalDataSource(
pokemonLocalDataSource: PokemonLocalDataSource,
typeDao: TypeDao
): TypeLocalDataSource = TypeLocalDataSource(pokemonLocalDataSource, typeDao)
database: ComposeDexDatabase
): TypeLocalDataSource = TypeLocalDataSource(database)

@Provides
fun provideGenerationLocalDataSource(
pokemonLocalDataSource: PokemonLocalDataSource,
generationDao: GenerationDao
database: ComposeDexDatabase
): GenerationLocalDataSource =
GenerationLocalDataSource(pokemonLocalDataSource, generationDao)
GenerationLocalDataSource(database)
}