Fix opening recipes on v0.5.6

This commit is contained in:
Kirill Kamakin
2022-10-29 17:46:28 +02:00
parent 45b1b07372
commit 47addc3b90
17 changed files with 192 additions and 44 deletions

View File

@@ -5,14 +5,15 @@ import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.baseurl.BaseURLStorage
import gq.kirmanak.mealient.data.baseurl.VersionDataSource
import gq.kirmanak.mealient.data.baseurl.VersionInfo
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
import gq.kirmanak.mealient.data.recipes.network.RecipeSummaryInfo
import gq.kirmanak.mealient.datasource.MealieDataSource
import gq.kirmanak.mealient.datasource.models.AddRecipeRequest
import gq.kirmanak.mealient.datasource.models.GetRecipeResponse
import gq.kirmanak.mealient.datasource.models.NetworkError
import gq.kirmanak.mealient.datasource.v1.MealieDataSourceV1
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
import gq.kirmanak.mealient.extensions.toFullRecipeInfo
import gq.kirmanak.mealient.extensions.toRecipeSummaryInfo
import gq.kirmanak.mealient.extensions.toVersionInfo
import javax.inject.Inject
@@ -50,8 +51,15 @@ class MealieDataSourceWrapper @Inject constructor(
}
}
override suspend fun requestRecipeInfo(slug: String): GetRecipeResponse =
withAuthHeader { token -> source.requestRecipeInfo(getUrl(), token, slug) }
override suspend fun requestRecipeInfo(slug: String): FullRecipeInfo =
withAuthHeader { token ->
val url = getUrl()
if (isV1()) {
v1Source.requestRecipeInfo(url, token, slug).toFullRecipeInfo()
} else {
source.requestRecipeInfo(url, token, slug).toFullRecipeInfo()
}
}
private suspend fun getUrl() = baseURLStorage.requireBaseURL()

View File

@@ -1,7 +1,7 @@
package gq.kirmanak.mealient.data.recipes
import androidx.paging.Pager
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeInfo
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
interface RecipeRepo {
@@ -9,5 +9,5 @@ interface RecipeRepo {
suspend fun clearLocalData()
suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeInfo
suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeEntity
}

View File

@@ -1,10 +1,10 @@
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.FullRecipeInfo
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.datasource.models.GetRecipeResponse
interface RecipeStorage {
suspend fun saveRecipes(recipes: List<RecipeSummaryInfo>)
@@ -15,7 +15,7 @@ interface RecipeStorage {
suspend fun clearAllLocalData()
suspend fun saveRecipeInfo(recipe: GetRecipeResponse)
suspend fun saveRecipeInfo(recipe: FullRecipeInfo)
suspend fun queryRecipeInfo(recipeId: String): FullRecipeInfo
suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity
}

View File

@@ -2,11 +2,11 @@ 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.*
import gq.kirmanak.mealient.datasource.models.GetRecipeResponse
import gq.kirmanak.mealient.extensions.recipeEntity
import gq.kirmanak.mealient.extensions.toRecipeEntity
import gq.kirmanak.mealient.extensions.toRecipeIngredientEntity
@@ -113,7 +113,7 @@ class RecipeStorageImpl @Inject constructor(
}
}
override suspend fun saveRecipeInfo(recipe: GetRecipeResponse) {
override suspend fun saveRecipeInfo(recipe: FullRecipeInfo) {
logger.v { "saveRecipeInfo() called with: recipe = $recipe" }
db.withTransaction {
recipeDao.insertRecipe(recipe.toRecipeEntity())
@@ -132,7 +132,7 @@ class RecipeStorageImpl @Inject constructor(
}
}
override suspend fun queryRecipeInfo(recipeId: String): FullRecipeInfo {
override suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity {
logger.v { "queryRecipeInfo() called with: recipeId = $recipeId" }
val fullRecipeInfo = checkNotNull(recipeDao.queryFullRecipeInfo(recipeId)) {
"Can't find recipe by id $recipeId in DB"

View File

@@ -7,7 +7,7 @@ import androidx.paging.PagingConfig
import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeInfo
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
import gq.kirmanak.mealient.logging.Logger
@@ -38,7 +38,7 @@ class RecipeRepoImpl @Inject constructor(
storage.clearAllLocalData()
}
override suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeInfo {
override suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeEntity {
logger.v { "loadRecipeInfo() called with: recipeId = $recipeId, recipeSlug = $recipeSlug" }
runCatchingExceptCancel {

View File

@@ -0,0 +1,34 @@
package gq.kirmanak.mealient.data.recipes.network
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
data class FullRecipeInfo(
val remoteId: String,
val name: String,
val slug: String,
val image: String,
val description: String,
val recipeCategories: List<String>,
val tags: List<String>,
val rating: Int?,
val dateAdded: LocalDate,
val dateUpdated: LocalDateTime,
val recipeYield: String,
val recipeIngredients: List<RecipeIngredientInfo>,
val recipeInstructions: List<RecipeInstructionInfo>,
)
data class RecipeIngredientInfo(
val title: String,
val note: String,
val unit: String,
val food: String,
val disableAmount: Boolean,
val quantity: Double,
)
data class RecipeInstructionInfo(
val title: String,
val text: String,
)

View File

@@ -1,9 +1,7 @@
package gq.kirmanak.mealient.data.recipes.network
import gq.kirmanak.mealient.datasource.models.GetRecipeResponse
interface RecipeDataSource {
suspend fun requestRecipes(start: Int, limit: Int): List<RecipeSummaryInfo>
suspend fun requestRecipeInfo(slug: String): GetRecipeResponse
suspend fun requestRecipeInfo(slug: String): FullRecipeInfo
}

View File

@@ -1,23 +1,24 @@
package gq.kirmanak.mealient.extensions
import gq.kirmanak.mealient.data.baseurl.VersionInfo
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeIngredientInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeInstructionInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeSummaryInfo
import gq.kirmanak.mealient.database.recipe.entity.RecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeIngredientEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeInstructionEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.datasource.models.*
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
import gq.kirmanak.mealient.datasource.v1.models.*
import gq.kirmanak.mealient.datastore.recipe.AddRecipeDraft
fun GetRecipeResponse.toRecipeEntity() = RecipeEntity(
fun FullRecipeInfo.toRecipeEntity() = RecipeEntity(
remoteId = remoteId,
recipeYield = recipeYield
)
fun GetRecipeIngredientResponse.toRecipeIngredientEntity(remoteId: String) =
RecipeIngredientEntity(
fun RecipeIngredientInfo.toRecipeIngredientEntity(remoteId: String) = RecipeIngredientEntity(
recipeId = remoteId,
title = title,
note = note,
@@ -27,8 +28,7 @@ fun GetRecipeIngredientResponse.toRecipeIngredientEntity(remoteId: String) =
quantity = quantity
)
fun GetRecipeInstructionResponse.toRecipeInstructionEntity(remoteId: String) =
RecipeInstructionEntity(
fun RecipeInstructionInfo.toRecipeInstructionEntity(remoteId: String) = RecipeInstructionEntity(
recipeId = remoteId,
title = title,
text = text
@@ -99,3 +99,63 @@ fun AddRecipeRequest.toDraft(): AddRecipeDraft = AddRecipeDraft(
isRecipePublic = settings.public,
areCommentsDisabled = settings.disableComments,
)
fun GetRecipeResponse.toFullRecipeInfo() = FullRecipeInfo(
remoteId = remoteId.toString(),
name = name,
slug = slug,
image = image,
description = description,
recipeCategories = recipeCategories,
tags = tags,
rating = rating,
dateAdded = dateAdded,
dateUpdated = dateUpdated,
recipeYield = recipeYield,
recipeIngredients = recipeIngredients.map { it.toRecipeIngredientInfo() },
recipeInstructions = recipeInstructions.map { it.toRecipeInstructionInfo() }
)
fun GetRecipeIngredientResponse.toRecipeIngredientInfo() = RecipeIngredientInfo(
title = title,
note = note,
unit = unit,
food = food,
disableAmount = disableAmount,
quantity = quantity
)
fun GetRecipeInstructionResponse.toRecipeInstructionInfo() = RecipeInstructionInfo(
title = title,
text = text
)
fun GetRecipeResponseV1.toFullRecipeInfo() = FullRecipeInfo(
remoteId = remoteId,
name = name,
slug = slug,
image = image,
description = description,
recipeCategories = recipeCategories,
tags = tags,
rating = rating,
dateAdded = dateAdded,
dateUpdated = dateUpdated,
recipeYield = recipeYield,
recipeIngredients = recipeIngredients.map { it.toRecipeIngredientInfo() },
recipeInstructions = recipeInstructions.map { it.toRecipeInstructionInfo() }
)
fun GetRecipeIngredientResponseV1.toRecipeIngredientInfo() = RecipeIngredientInfo(
title = title,
note = note,
unit = unit,
food = food,
disableAmount = disableAmount,
quantity = quantity
)
fun GetRecipeInstructionResponseV1.toRecipeInstructionInfo() = RecipeInstructionInfo(
title = title,
text = text
)

View File

@@ -1,9 +1,9 @@
package gq.kirmanak.mealient.ui.recipes.info
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeInfo
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
data class RecipeInfoUiState(
val areIngredientsVisible: Boolean = false,
val areInstructionsVisible: Boolean = false,
val recipeInfo: FullRecipeInfo? = null,
val recipeInfo: FullRecipeEntity? = null,
)

View File

@@ -174,7 +174,7 @@ object RecipeImplTestData {
quantity = 2
)
val FULL_CAKE_INFO_ENTITY = FullRecipeInfo(
val FULL_CAKE_INFO_ENTITY = FullRecipeEntity(
recipeEntity = CAKE_RECIPE_ENTITY,
recipeSummaryEntity = CAKE_RECIPE_SUMMARY_ENTITY,
recipeIngredients = listOf(
@@ -228,7 +228,7 @@ object RecipeImplTestData {
text = "Boil the ingredients"
)
val FULL_PORRIDGE_INFO_ENTITY = FullRecipeInfo(
val FULL_PORRIDGE_INFO_ENTITY = FullRecipeEntity(
recipeEntity = PORRIDGE_RECIPE_ENTITY_FULL,
recipeSummaryEntity = PORRIDGE_RECIPE_SUMMARY_ENTITY,
recipeIngredients = listOf(

View File

@@ -66,7 +66,7 @@ interface RecipeDao {
@Transaction
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) // The lint is wrong, the columns are actually used
@Query("SELECT * FROM recipe JOIN recipe_summaries ON recipe.remote_id = recipe_summaries.remote_id JOIN recipe_ingredient ON recipe_ingredient.recipe_id = recipe.remote_id JOIN recipe_instruction ON recipe_instruction.recipe_id = recipe.remote_id WHERE recipe.remote_id = :recipeId")
suspend fun queryFullRecipeInfo(recipeId: String): FullRecipeInfo?
suspend fun queryFullRecipeInfo(recipeId: String): FullRecipeEntity?
@Query("DELETE FROM recipe_ingredient WHERE recipe_id = :recipeId")
suspend fun deleteRecipeIngredients(recipeId: String)

View File

@@ -3,7 +3,7 @@ package gq.kirmanak.mealient.database.recipe.entity
import androidx.room.Embedded
import androidx.room.Relation
data class FullRecipeInfo(
data class FullRecipeEntity(
@Embedded val recipeEntity: RecipeEntity,
@Relation(
parentColumn = "remote_id",

View File

@@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class GetRecipeResponse(
@SerialName("id") val remoteId: String,
@SerialName("id") val remoteId: Int,
@SerialName("name") val name: String,
@SerialName("slug") val slug: String,
@SerialName("image") val image: String,

View File

@@ -2,6 +2,7 @@ package gq.kirmanak.mealient.datasource.v1
import gq.kirmanak.mealient.datasource.DataSourceModule.Companion.AUTHORIZATION_HEADER_NAME
import gq.kirmanak.mealient.datasource.models.*
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
import gq.kirmanak.mealient.datasource.v1.models.GetRecipesResponseV1
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
import retrofit2.http.*
@@ -40,5 +41,5 @@ interface MealieServiceV1 {
suspend fun getRecipe(
@Url url: String,
@Header(AUTHORIZATION_HEADER_NAME) token: String?,
): GetRecipeResponse
): GetRecipeResponseV1
}

View File

@@ -0,0 +1,14 @@
package gq.kirmanak.mealient.datasource.v1.models
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GetRecipeIngredientResponseV1(
@SerialName("title") val title: String = "",
@SerialName("note") val note: String = "",
@SerialName("unit") val unit: String = "",
@SerialName("food") val food: String = "",
@SerialName("disableAmount") val disableAmount: Boolean,
@SerialName("quantity") val quantity: Double,
)

View File

@@ -0,0 +1,10 @@
package gq.kirmanak.mealient.datasource.v1.models
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GetRecipeInstructionResponseV1(
@SerialName("title") val title: String = "",
@SerialName("text") val text: String,
)

View File

@@ -0,0 +1,23 @@
package gq.kirmanak.mealient.datasource.v1.models
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GetRecipeResponseV1(
@SerialName("id") val remoteId: String,
@SerialName("name") val name: String,
@SerialName("slug") val slug: String,
@SerialName("image") val image: String,
@SerialName("description") val description: String = "",
@SerialName("recipeCategory") val recipeCategories: List<String>,
@SerialName("tags") val tags: List<String>,
@SerialName("rating") val rating: Int?,
@SerialName("dateAdded") val dateAdded: LocalDate,
@SerialName("dateUpdated") val dateUpdated: LocalDateTime,
@SerialName("recipeYield") val recipeYield: String = "",
@SerialName("recipeIngredient") val recipeIngredients: List<GetRecipeIngredientResponseV1>,
@SerialName("recipeInstructions") val recipeInstructions: List<GetRecipeInstructionResponseV1>,
)