Save isFavorite flag to DB for recipes
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package gq.kirmanak.mealient.data.configuration
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.MainCoroutineDispatcher
|
||||
|
||||
interface AppDispatchers {
|
||||
val io: CoroutineDispatcher
|
||||
val main: MainCoroutineDispatcher
|
||||
val default: CoroutineDispatcher
|
||||
val unconfined: CoroutineDispatcher
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package gq.kirmanak.mealient.data.configuration
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AppDispatchersImpl @Inject constructor() : AppDispatchers {
|
||||
|
||||
override val io = Dispatchers.IO
|
||||
|
||||
override val main = Dispatchers.Main
|
||||
|
||||
override val default = Dispatchers.Default
|
||||
|
||||
override val unconfined = Dispatchers.Unconfined
|
||||
}
|
||||
@@ -64,4 +64,8 @@ class MealieDataSourceWrapper @Inject constructor(
|
||||
ServerVersion.V1 -> v1Source.parseRecipeFromURL(parseRecipeURLInfo.toV1Request())
|
||||
}
|
||||
|
||||
override suspend fun getFavoriteRecipes(): List<String> = when (getVersion()) {
|
||||
ServerVersion.V0 -> v0Source.requestUserInfo().favoriteRecipes
|
||||
ServerVersion.V1 -> v1Source.requestUserInfo().favoriteRecipes
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,15 @@ package gq.kirmanak.mealient.data.recipes.db
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.data.recipes.network.RecipeSummaryInfo
|
||||
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
|
||||
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||
|
||||
interface RecipeStorage {
|
||||
suspend fun saveRecipes(recipes: List<RecipeSummaryInfo>)
|
||||
suspend fun saveRecipes(recipes: List<RecipeSummaryEntity>)
|
||||
|
||||
fun queryRecipes(query: String?): PagingSource<Int, RecipeSummaryEntity>
|
||||
|
||||
suspend fun refreshAll(recipes: List<RecipeSummaryInfo>)
|
||||
suspend fun refreshAll(recipes: List<RecipeSummaryEntity>)
|
||||
|
||||
suspend fun clearAllLocalData()
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package gq.kirmanak.mealient.data.recipes.db
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.withTransaction
|
||||
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.data.recipes.network.RecipeSummaryInfo
|
||||
import gq.kirmanak.mealient.database.AppDb
|
||||
import gq.kirmanak.mealient.database.recipe.RecipeDao
|
||||
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
|
||||
@@ -11,7 +10,6 @@ import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeIngredientEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeInstructionEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@@ -23,11 +21,9 @@ class RecipeStorageImpl @Inject constructor(
|
||||
) : RecipeStorage {
|
||||
private val recipeDao: RecipeDao by lazy { db.recipeDao() }
|
||||
|
||||
override suspend fun saveRecipes(recipes: List<RecipeSummaryInfo>) {
|
||||
override suspend fun saveRecipes(recipes: List<RecipeSummaryEntity>) {
|
||||
logger.v { "saveRecipes() called with $recipes" }
|
||||
val entities = recipes.map { it.toRecipeSummaryEntity() }
|
||||
logger.v { "saveRecipes: entities = $entities" }
|
||||
db.withTransaction { recipeDao.insertRecipes(entities) }
|
||||
db.withTransaction { recipeDao.insertRecipes(recipes) }
|
||||
}
|
||||
|
||||
override fun queryRecipes(query: String?): PagingSource<Int, RecipeSummaryEntity> {
|
||||
@@ -36,7 +32,7 @@ class RecipeStorageImpl @Inject constructor(
|
||||
else recipeDao.queryRecipesByPages(query)
|
||||
}
|
||||
|
||||
override suspend fun refreshAll(recipes: List<RecipeSummaryInfo>) {
|
||||
override suspend fun refreshAll(recipes: List<RecipeSummaryEntity>) {
|
||||
logger.v { "refreshAll() called with: recipes = $recipes" }
|
||||
db.withTransaction {
|
||||
recipeDao.removeAllRecipes()
|
||||
|
||||
@@ -66,7 +66,7 @@ class RecipeRepoImpl @Inject constructor(
|
||||
override suspend fun refreshRecipes() {
|
||||
logger.v { "refreshRecipes() called" }
|
||||
runCatchingExceptCancel {
|
||||
storage.refreshAll(dataSource.requestRecipes(0, INITIAL_LOAD_PAGE_SIZE))
|
||||
mediator.updateRecipes(0, INITIAL_LOAD_PAGE_SIZE)
|
||||
}.onFailure {
|
||||
logger.e(it) { "Can't refresh recipes" }
|
||||
}
|
||||
|
||||
@@ -4,11 +4,16 @@ import androidx.annotation.VisibleForTesting
|
||||
import androidx.paging.*
|
||||
import androidx.paging.LoadType.PREPEND
|
||||
import androidx.paging.LoadType.REFRESH
|
||||
import gq.kirmanak.mealient.data.configuration.AppDispatchers
|
||||
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
||||
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
|
||||
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
|
||||
import gq.kirmanak.mealient.extensions.toRecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -19,14 +24,14 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
private val network: RecipeDataSource,
|
||||
private val pagingSourceFactory: RecipePagingSourceFactory,
|
||||
private val logger: Logger,
|
||||
private val dispatchers: AppDispatchers,
|
||||
) : RemoteMediator<Int, RecipeSummaryEntity>() {
|
||||
|
||||
@VisibleForTesting
|
||||
var lastRequestEnd: Int = 0
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, RecipeSummaryEntity>
|
||||
loadType: LoadType, state: PagingState<Int, RecipeSummaryEntity>
|
||||
): MediatorResult {
|
||||
logger.v { "load() called with: lastRequestEnd = $lastRequestEnd, loadType = $loadType, state = $state" }
|
||||
|
||||
@@ -39,10 +44,7 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
val limit = if (loadType == REFRESH) state.config.initialLoadSize else state.config.pageSize
|
||||
|
||||
val count: Int = runCatchingExceptCancel {
|
||||
val recipes = network.requestRecipes(start, limit)
|
||||
if (loadType == REFRESH) storage.refreshAll(recipes)
|
||||
else storage.saveRecipes(recipes)
|
||||
recipes.size
|
||||
updateRecipes(start, limit, loadType)
|
||||
}.getOrElse {
|
||||
logger.e(it) { "load: can't load recipes" }
|
||||
return MediatorResult.Error(it)
|
||||
@@ -58,4 +60,23 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
lastRequestEnd = start + count
|
||||
return MediatorResult.Success(endOfPaginationReached = count < limit)
|
||||
}
|
||||
|
||||
suspend fun updateRecipes(
|
||||
start: Int,
|
||||
limit: Int,
|
||||
loadType: LoadType = REFRESH,
|
||||
): Int = coroutineScope {
|
||||
val deferredRecipes = async { network.requestRecipes(start, limit) }
|
||||
val favorites = network.getFavoriteRecipes().toHashSet()
|
||||
val recipes = deferredRecipes.await()
|
||||
val entities = withContext(dispatchers.default) {
|
||||
recipes.map { recipe ->
|
||||
val isFavorite = favorites.contains(recipe.slug)
|
||||
recipe.toRecipeSummaryEntity(isFavorite)
|
||||
}
|
||||
}
|
||||
if (loadType == REFRESH) storage.refreshAll(entities)
|
||||
else storage.saveRecipes(entities)
|
||||
recipes.size
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,6 @@ interface RecipeDataSource {
|
||||
suspend fun requestRecipes(start: Int, limit: Int): List<RecipeSummaryInfo>
|
||||
|
||||
suspend fun requestRecipeInfo(slug: String): FullRecipeInfo
|
||||
|
||||
suspend fun getFavoriteRecipes(): List<String>
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import gq.kirmanak.mealient.architecture.configuration.BuildConfiguration
|
||||
import gq.kirmanak.mealient.data.configuration.AppDispatchers
|
||||
import gq.kirmanak.mealient.data.configuration.AppDispatchersImpl
|
||||
import gq.kirmanak.mealient.data.configuration.BuildConfigurationImpl
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -15,4 +17,8 @@ interface ArchitectureModule {
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindBuildConfiguration(buildConfigurationImpl: BuildConfigurationImpl): BuildConfiguration
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindAppDispatchers(appDispatchersImpl: AppDispatchersImpl): AppDispatchers
|
||||
}
|
||||
@@ -80,7 +80,7 @@ fun GetRecipeSummaryResponseV1.toRecipeSummaryInfo() = RecipeSummaryInfo(
|
||||
imageId = remoteId,
|
||||
)
|
||||
|
||||
fun RecipeSummaryInfo.toRecipeSummaryEntity() = RecipeSummaryEntity(
|
||||
fun RecipeSummaryInfo.toRecipeSummaryEntity(isFavorite: Boolean) = RecipeSummaryEntity(
|
||||
remoteId = remoteId,
|
||||
name = name,
|
||||
slug = slug,
|
||||
@@ -88,6 +88,7 @@ fun RecipeSummaryInfo.toRecipeSummaryEntity() = RecipeSummaryEntity(
|
||||
dateAdded = dateAdded,
|
||||
dateUpdated = dateUpdated,
|
||||
imageId = imageId,
|
||||
isFavorite = isFavorite,
|
||||
)
|
||||
|
||||
fun VersionResponseV0.toVersionInfo() = VersionInfo(version)
|
||||
|
||||
198
database/schemas/gq.kirmanak.mealient.database.AppDb/8.json
Normal file
198
database/schemas/gq.kirmanak.mealient.database.AppDb/8.json
Normal file
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 8,
|
||||
"identityHash": "793673e401425db36544918dae6bf4c1",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "recipe_summaries",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`remote_id` TEXT NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `description` TEXT NOT NULL, `date_added` INTEGER NOT NULL, `date_updated` INTEGER NOT NULL, `image_id` TEXT, `is_favorite` INTEGER NOT NULL DEFAULT false, PRIMARY KEY(`remote_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remote_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "slug",
|
||||
"columnName": "slug",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "description",
|
||||
"columnName": "description",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dateAdded",
|
||||
"columnName": "date_added",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dateUpdated",
|
||||
"columnName": "date_updated",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "imageId",
|
||||
"columnName": "image_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "is_favorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "false"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"remote_id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "recipe",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`remote_id` TEXT NOT NULL, `recipe_yield` TEXT NOT NULL, `disable_amounts` INTEGER NOT NULL DEFAULT true, PRIMARY KEY(`remote_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remote_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "recipeYield",
|
||||
"columnName": "recipe_yield",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "disableAmounts",
|
||||
"columnName": "disable_amounts",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "true"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"remote_id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "recipe_ingredient",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `recipe_id` TEXT NOT NULL, `note` TEXT NOT NULL, `food` TEXT, `unit` TEXT, `quantity` REAL, `title` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "localId",
|
||||
"columnName": "local_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "recipeId",
|
||||
"columnName": "recipe_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "note",
|
||||
"columnName": "note",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "food",
|
||||
"columnName": "food",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "unit",
|
||||
"columnName": "unit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "quantity",
|
||||
"columnName": "quantity",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"local_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "recipe_instruction",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `recipe_id` TEXT NOT NULL, `text` TEXT NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "localId",
|
||||
"columnName": "local_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "recipeId",
|
||||
"columnName": "recipe_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"local_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '793673e401425db36544918dae6bf4c1')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import gq.kirmanak.mealient.database.recipe.RecipeDao
|
||||
import gq.kirmanak.mealient.database.recipe.entity.*
|
||||
|
||||
@Database(
|
||||
version = 7,
|
||||
version = 8,
|
||||
entities = [
|
||||
RecipeSummaryEntity::class,
|
||||
RecipeEntity::class,
|
||||
@@ -20,6 +20,7 @@ import gq.kirmanak.mealient.database.recipe.entity.*
|
||||
AutoMigration(from = 4, to = 5, spec = AppDb.From4To5Migration::class),
|
||||
AutoMigration(from = 5, to = 6, spec = AppDb.From5To6Migration::class),
|
||||
AutoMigration(from = 6, to = 7),
|
||||
AutoMigration(from = 7, to = 8),
|
||||
]
|
||||
)
|
||||
@TypeConverters(RoomTypeConverters::class)
|
||||
|
||||
@@ -15,4 +15,5 @@ data class RecipeSummaryEntity(
|
||||
@ColumnInfo(name = "date_added") val dateAdded: LocalDate,
|
||||
@ColumnInfo(name = "date_updated") val dateUpdated: LocalDateTime,
|
||||
@ColumnInfo(name = "image_id") val imageId: String?,
|
||||
@ColumnInfo(name = "is_favorite", defaultValue = "false") val isFavorite: Boolean,
|
||||
)
|
||||
@@ -5,13 +5,13 @@ interface NetworkRequestWrapper {
|
||||
suspend fun <T> makeCall(
|
||||
block: suspend () -> T,
|
||||
logMethod: () -> String,
|
||||
logParameters: () -> String,
|
||||
logParameters: (() -> String)? = null,
|
||||
): Result<T>
|
||||
|
||||
suspend fun <T> makeCallAndHandleUnauthorized(
|
||||
block: suspend () -> T,
|
||||
logMethod: () -> String,
|
||||
logParameters: () -> String,
|
||||
logParameters: (() -> String)? = null,
|
||||
): T
|
||||
|
||||
}
|
||||
@@ -16,18 +16,40 @@ class NetworkRequestWrapperImpl @Inject constructor(
|
||||
override suspend fun <T> makeCall(
|
||||
block: suspend () -> T,
|
||||
logMethod: () -> String,
|
||||
logParameters: () -> String,
|
||||
logParameters: (() -> String)?,
|
||||
): Result<T> {
|
||||
logger.v { "${logMethod()} called with: ${logParameters()}" }
|
||||
logger.v {
|
||||
if (logParameters == null) {
|
||||
"${logMethod()} called"
|
||||
} else {
|
||||
"${logMethod()} called with: ${logParameters()}"
|
||||
}
|
||||
}
|
||||
return runCatchingExceptCancel { block() }
|
||||
.onFailure { logger.e(it) { "${logMethod()} request failed with: ${logParameters()}" } }
|
||||
.onSuccess { logger.d { "${logMethod()} request succeeded with ${logParameters()}, result = $it" } }
|
||||
.onFailure {
|
||||
logger.e(it) {
|
||||
if (logParameters == null) {
|
||||
"${logMethod()} request failed"
|
||||
} else {
|
||||
"${logMethod()} request failed with: ${logParameters()}"
|
||||
}
|
||||
}
|
||||
}
|
||||
.onSuccess {
|
||||
logger.d {
|
||||
if (logParameters == null) {
|
||||
"${logMethod()} request succeeded, result = $it"
|
||||
} else {
|
||||
"${logMethod()} request succeeded with: ${logParameters()}, result = $it"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T> makeCallAndHandleUnauthorized(
|
||||
block: suspend () -> T,
|
||||
logMethod: () -> String,
|
||||
logParameters: () -> String
|
||||
logParameters: (() -> String)?
|
||||
): T = makeCall(block, logMethod, logParameters).getOrElse {
|
||||
throw if (it is HttpException && it.code() in listOf(401, 403)) {
|
||||
NetworkError.Unauthorized(it)
|
||||
|
||||
@@ -4,6 +4,7 @@ import gq.kirmanak.mealient.datasource.v0.models.AddRecipeRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.CreateApiTokenRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeSummaryResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetUserInfoResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.ParseRecipeURLRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0
|
||||
|
||||
@@ -21,8 +22,7 @@ interface MealieDataSourceV0 {
|
||||
password: String,
|
||||
): String
|
||||
|
||||
suspend fun getVersionInfo(
|
||||
): VersionResponseV0
|
||||
suspend fun getVersionInfo(): VersionResponseV0
|
||||
|
||||
suspend fun requestRecipes(
|
||||
start: Int,
|
||||
@@ -40,4 +40,6 @@ interface MealieDataSourceV0 {
|
||||
suspend fun createApiToken(
|
||||
request: CreateApiTokenRequestV0,
|
||||
): String
|
||||
|
||||
suspend fun requestUserInfo(): GetUserInfoResponseV0
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import gq.kirmanak.mealient.datasource.v0.models.CreateApiTokenRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.ErrorDetailV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeSummaryResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetUserInfoResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.ParseRecipeURLRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0
|
||||
import kotlinx.serialization.SerializationException
|
||||
@@ -49,7 +50,6 @@ class MealieDataSourceV0Impl @Inject constructor(
|
||||
override suspend fun getVersionInfo(): VersionResponseV0 = networkRequestWrapper.makeCall(
|
||||
block = { service.getVersion() },
|
||||
logMethod = { "getVersionInfo" },
|
||||
logParameters = { "" },
|
||||
).getOrElse {
|
||||
throw when (it) {
|
||||
is HttpException, is SerializationException -> NetworkError.NotMealie(it)
|
||||
@@ -90,4 +90,11 @@ class MealieDataSourceV0Impl @Inject constructor(
|
||||
logMethod = { "createApiToken" },
|
||||
logParameters = { "request = $request" }
|
||||
)
|
||||
|
||||
override suspend fun requestUserInfo(): GetUserInfoResponseV0 {
|
||||
return networkRequestWrapper.makeCallAndHandleUnauthorized(
|
||||
block = { service.getUserSelfInfo() },
|
||||
logMethod = { "requestUserInfo" },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,7 @@ interface MealieServiceV0 {
|
||||
suspend fun createApiToken(
|
||||
@Body request: CreateApiTokenRequestV0,
|
||||
): String
|
||||
|
||||
@GET("/api/users/self")
|
||||
suspend fun getUserSelfInfo(): GetUserInfoResponseV0
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package gq.kirmanak.mealient.datasource.v0.models
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GetUserInfoResponseV0(
|
||||
@SerialName("favoriteRecipes") val favoriteRecipes: List<String> = emptyList(),
|
||||
)
|
||||
@@ -5,6 +5,7 @@ import gq.kirmanak.mealient.datasource.v1.models.CreateApiTokenResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.CreateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetUserInfoResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.ParseRecipeURLRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.UpdateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
|
||||
@@ -47,4 +48,6 @@ interface MealieDataSourceV1 {
|
||||
suspend fun createApiToken(
|
||||
request: CreateApiTokenRequestV1,
|
||||
): CreateApiTokenResponseV1
|
||||
|
||||
suspend fun requestUserInfo(): GetUserInfoResponseV1
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import gq.kirmanak.mealient.datasource.v1.models.CreateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.ErrorDetailV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetUserInfoResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.ParseRecipeURLRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.UpdateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
|
||||
@@ -60,7 +61,6 @@ class MealieDataSourceV1Impl @Inject constructor(
|
||||
override suspend fun getVersionInfo(): VersionResponseV1 = networkRequestWrapper.makeCall(
|
||||
block = { service.getVersion() },
|
||||
logMethod = { "getVersionInfo" },
|
||||
logParameters = { "" },
|
||||
).getOrElse {
|
||||
throw when (it) {
|
||||
is HttpException, is SerializationException -> NetworkError.NotMealie(it)
|
||||
@@ -101,5 +101,12 @@ class MealieDataSourceV1Impl @Inject constructor(
|
||||
logMethod = { "createApiToken" },
|
||||
logParameters = { "request = $request" }
|
||||
)
|
||||
|
||||
override suspend fun requestUserInfo(): GetUserInfoResponseV1 {
|
||||
return networkRequestWrapper.makeCallAndHandleUnauthorized(
|
||||
block = { service.getUserSelfInfo() },
|
||||
logMethod = { "requestUserInfo" },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,4 +46,7 @@ interface MealieServiceV1 {
|
||||
suspend fun createApiToken(
|
||||
@Body request: CreateApiTokenRequestV1,
|
||||
): CreateApiTokenResponseV1
|
||||
|
||||
@GET("/api/users/self")
|
||||
suspend fun getUserSelfInfo(): GetUserInfoResponseV1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package gq.kirmanak.mealient.datasource.v1.models
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GetUserInfoResponseV1(
|
||||
@SerialName("favoriteRecipes") val favoriteRecipes: List<String> = emptyList(),
|
||||
)
|
||||
Reference in New Issue
Block a user