Implement shopping lists screen (#129)
* Initialize shopping lists feature * Start shopping lists screen with Compose * Add icon to shopping list name * Add shopping lists to menu * Set max size for the list * Replace compose-adapter with accompanist * Remove unused fields from shopping lists response * Show list of shopping lists from BE * Hide shopping lists if Mealie is 0.5.6 * Add shopping list item click listener * Create material app theme for Compose * Use shorter names * Load shopping lists by pages and save to db * Make page handling logic match recipes * Add swipe to refresh to shopping lists * Extract SwipeToRefresh Composable * Make LazyPagingColumn generic * Show refresh only when mediator is refreshing * Do not refresh automatically * Allow controlling Activity state from modules * Implement navigating to shopping list screen * Move Compose libraries setup to a plugin * Implement loading full shopping list info * Move Storage classes to database module * Save shopping list items to DB * Use separate names for separate ids * Do only one DB version update * Use unique names for all columns * Display shopping list items * Move OperationUiState to ui module * Subscribe to shopping lists updates * Indicate progress with progress bar * Use strings from resources * Format shopping list item quantities * Hide unit/food/note/quantity if they are not set * Implement updating shopping list item checked state * Remove unnecessary null checks * Disable checkbox when it is being updated * Split shopping list screen into composables * Show items immediately if they are saved * Fix showing "list is empty" before the items * Show Snackbar when error happens * Reduce shopping list items paddings * Remove shopping lists when URL is changed * Add error/empty state handling to shopping lists * Fix empty error state * Fix tests compilation * Add margin between text and button * Add divider between checked and unchecked items * Move divider to the item * Refresh the shopping lists on authentication * Use retry when necessary * Remove excessive logging * Fix pages bounds check * Move FlowExtensionsTest * Update Compose version * Fix showing loading indicator for shopping lists * Add Russian translation * Fix SDK version lint check * Rename parameter to match interface * Add DB migration TODO * Get rid of DB migrations * Do not use pagination with shopping lists * Cleanup after the pagination removal * Load shopping list items * Remove shopping lists storage * Rethrow CancellationException in LoadingHelper * Add pull-to-refresh on shopping list screen * Extract LazyColumnWithLoadingState * Split refresh errors and loading state * Reuse LazyColumnWithLoadingState for shopping list items * Remove paging-compose dependency * Refresh shopping list items on authentication * Disable missing translation lint check * Update Compose and Kotlin versions * Fix order of checked items * Hide useless information from a shopping list item
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
package gq.kirmanak.mealient.model_mapper
|
||||
|
||||
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.AddRecipeInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeIngredientInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeInstructionInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeSettingsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.datasource.models.FullShoppingListInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ParseRecipeURLInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeIngredientInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeInstructionInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeSettingsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeSummaryInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListItemInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListItemRecipeReferenceInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.VersionInfo
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeIngredientV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeInstructionV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeSettingsV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeIngredientResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeInstructionResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeSummaryResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.ParseRecipeURLRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeIngredientV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeInstructionV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeSettingsV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.CreateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeIngredientResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeInstructionResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSettingsResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListItemRecipeReferenceFullResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListItemResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListsResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListsSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.ParseRecipeURLRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.UpdateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
|
||||
import gq.kirmanak.mealient.datastore.recipe.AddRecipeDraft
|
||||
|
||||
interface ModelMapper {
|
||||
|
||||
fun toRecipeEntity(fullRecipeInfo: FullRecipeInfo): RecipeEntity
|
||||
|
||||
fun toRecipeIngredientEntity(
|
||||
recipeIngredientInfo: RecipeIngredientInfo, remoteId: String
|
||||
): RecipeIngredientEntity
|
||||
|
||||
fun toRecipeInstructionEntity(
|
||||
recipeInstructionInfo: RecipeInstructionInfo, remoteId: String
|
||||
): RecipeInstructionEntity
|
||||
|
||||
fun toRecipeSummaryEntity(
|
||||
recipeSummaryInfo: RecipeSummaryInfo, isFavorite: Boolean
|
||||
): RecipeSummaryEntity
|
||||
|
||||
fun toAddRecipeInfo(addRecipeDraft: AddRecipeDraft): AddRecipeInfo
|
||||
|
||||
fun toDraft(addRecipeInfo: AddRecipeInfo): AddRecipeDraft
|
||||
|
||||
fun toVersionInfo(versionResponseV1: VersionResponseV1): VersionInfo
|
||||
|
||||
fun toFullRecipeInfo(getRecipeResponseV1: GetRecipeResponseV1): FullRecipeInfo
|
||||
|
||||
fun toRecipeSettingsInfo(getRecipeSettingsResponseV1: GetRecipeSettingsResponseV1?): RecipeSettingsInfo
|
||||
|
||||
fun toRecipeIngredientInfo(getRecipeIngredientResponseV1: GetRecipeIngredientResponseV1): RecipeIngredientInfo
|
||||
|
||||
fun toRecipeInstructionInfo(getRecipeInstructionResponseV1: GetRecipeInstructionResponseV1): RecipeInstructionInfo
|
||||
|
||||
fun toV1CreateRequest(addRecipeInfo: AddRecipeInfo): CreateRecipeRequestV1
|
||||
|
||||
fun toV1UpdateRequest(addRecipeInfo: AddRecipeInfo): UpdateRecipeRequestV1
|
||||
|
||||
fun toV1Settings(addRecipeSettingsInfo: AddRecipeSettingsInfo): AddRecipeSettingsV1
|
||||
|
||||
fun toV1Ingredient(addRecipeIngredientInfo: AddRecipeIngredientInfo): AddRecipeIngredientV1
|
||||
|
||||
fun toV1Instruction(addRecipeInstructionInfo: AddRecipeInstructionInfo): AddRecipeInstructionV1
|
||||
|
||||
fun toV1Request(parseRecipeURLInfo: ParseRecipeURLInfo): ParseRecipeURLRequestV1
|
||||
|
||||
fun toFullShoppingListInfo(getShoppingListResponseV1: GetShoppingListResponseV1): FullShoppingListInfo
|
||||
|
||||
fun toShoppingListItemInfo(
|
||||
getShoppingListItemResponseV1: GetShoppingListItemResponseV1,
|
||||
recipes: Map<String, List<GetShoppingListItemRecipeReferenceFullResponseV1>>
|
||||
): ShoppingListItemInfo
|
||||
|
||||
fun toShoppingListItemRecipeReferenceInfo(
|
||||
getShoppingListItemRecipeReferenceFullResponseV1: GetShoppingListItemRecipeReferenceFullResponseV1
|
||||
): ShoppingListItemRecipeReferenceInfo
|
||||
|
||||
fun toShoppingListsInfo(getShoppingListsResponseV1: GetShoppingListsResponseV1): ShoppingListsInfo
|
||||
|
||||
fun toShoppingListInfo(getShoppingListsSummaryResponseV1: GetShoppingListsSummaryResponseV1): ShoppingListInfo
|
||||
|
||||
fun toRecipeSummaryInfo(getRecipeSummaryResponseV1: GetRecipeSummaryResponseV1): RecipeSummaryInfo
|
||||
|
||||
fun toRecipeSummaryInfo(getRecipeSummaryResponseV0: GetRecipeSummaryResponseV0): RecipeSummaryInfo
|
||||
|
||||
fun toVersionInfo(versionResponseV0: VersionResponseV0): VersionInfo
|
||||
|
||||
fun toFullRecipeInfo(getRecipeResponseV0: GetRecipeResponseV0): FullRecipeInfo
|
||||
|
||||
fun toRecipeIngredientInfo(getRecipeIngredientResponseV0: GetRecipeIngredientResponseV0): RecipeIngredientInfo
|
||||
|
||||
fun toRecipeInstructionInfo(getRecipeInstructionResponseV0: GetRecipeInstructionResponseV0): RecipeInstructionInfo
|
||||
|
||||
fun toV0Request(addRecipeInfo: AddRecipeInfo): AddRecipeRequestV0
|
||||
|
||||
fun toV0Settings(addRecipeSettingsInfo: AddRecipeSettingsInfo): AddRecipeSettingsV0
|
||||
|
||||
fun toV0Ingredient(addRecipeIngredientInfo: AddRecipeIngredientInfo): AddRecipeIngredientV0
|
||||
|
||||
fun toV0Instruction(addRecipeInstructionInfo: AddRecipeInstructionInfo): AddRecipeInstructionV0
|
||||
|
||||
fun toV0Request(parseRecipeURLInfo: ParseRecipeURLInfo): ParseRecipeURLRequestV0
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
package gq.kirmanak.mealient.model_mapper
|
||||
|
||||
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.AddRecipeInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeIngredientInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeInstructionInfo
|
||||
import gq.kirmanak.mealient.datasource.models.AddRecipeSettingsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.datasource.models.FullShoppingListInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ParseRecipeURLInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeIngredientInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeInstructionInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeSettingsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.RecipeSummaryInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListItemInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListItemRecipeReferenceInfo
|
||||
import gq.kirmanak.mealient.datasource.models.ShoppingListsInfo
|
||||
import gq.kirmanak.mealient.datasource.models.VersionInfo
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeIngredientV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeInstructionV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeSettingsV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeIngredientResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeInstructionResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeSummaryResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.ParseRecipeURLRequestV0
|
||||
import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeIngredientV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeInstructionV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.AddRecipeSettingsV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.CreateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeIngredientResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeInstructionResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSettingsResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListItemRecipeReferenceFullResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListItemResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListsResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.GetShoppingListsSummaryResponseV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.ParseRecipeURLRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.UpdateRecipeRequestV1
|
||||
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
|
||||
import gq.kirmanak.mealient.datastore.recipe.AddRecipeDraft
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ModelMapperImpl @Inject constructor() : ModelMapper {
|
||||
|
||||
|
||||
override fun toRecipeEntity(fullRecipeInfo: FullRecipeInfo) = RecipeEntity(
|
||||
remoteId = fullRecipeInfo.remoteId,
|
||||
recipeYield = fullRecipeInfo.recipeYield,
|
||||
disableAmounts = fullRecipeInfo.settings.disableAmounts,
|
||||
)
|
||||
|
||||
override fun toRecipeIngredientEntity(
|
||||
recipeIngredientInfo: RecipeIngredientInfo, remoteId: String
|
||||
) = RecipeIngredientEntity(
|
||||
recipeId = remoteId,
|
||||
note = recipeIngredientInfo.note,
|
||||
unit = recipeIngredientInfo.unit,
|
||||
food = recipeIngredientInfo.food,
|
||||
quantity = recipeIngredientInfo.quantity,
|
||||
title = recipeIngredientInfo.title,
|
||||
)
|
||||
|
||||
override fun toRecipeInstructionEntity(
|
||||
recipeInstructionInfo: RecipeInstructionInfo, remoteId: String
|
||||
) = RecipeInstructionEntity(
|
||||
recipeId = remoteId, text = recipeInstructionInfo.text
|
||||
)
|
||||
|
||||
override fun toRecipeSummaryEntity(recipeSummaryInfo: RecipeSummaryInfo, isFavorite: Boolean) =
|
||||
RecipeSummaryEntity(
|
||||
remoteId = recipeSummaryInfo.remoteId,
|
||||
name = recipeSummaryInfo.name,
|
||||
slug = recipeSummaryInfo.slug,
|
||||
description = recipeSummaryInfo.description,
|
||||
dateAdded = recipeSummaryInfo.dateAdded,
|
||||
dateUpdated = recipeSummaryInfo.dateUpdated,
|
||||
imageId = recipeSummaryInfo.imageId,
|
||||
isFavorite = isFavorite,
|
||||
)
|
||||
|
||||
override fun toAddRecipeInfo(addRecipeDraft: AddRecipeDraft) = AddRecipeInfo(
|
||||
name = addRecipeDraft.recipeName,
|
||||
description = addRecipeDraft.recipeDescription,
|
||||
recipeYield = addRecipeDraft.recipeYield,
|
||||
recipeIngredient = addRecipeDraft.recipeIngredients.map { AddRecipeIngredientInfo(note = it) },
|
||||
recipeInstructions = addRecipeDraft.recipeInstructions.map { AddRecipeInstructionInfo(text = it) },
|
||||
settings = AddRecipeSettingsInfo(
|
||||
public = addRecipeDraft.isRecipePublic,
|
||||
disableComments = addRecipeDraft.areCommentsDisabled,
|
||||
)
|
||||
)
|
||||
|
||||
override fun toDraft(addRecipeInfo: AddRecipeInfo): AddRecipeDraft = AddRecipeDraft(
|
||||
recipeName = addRecipeInfo.name,
|
||||
recipeDescription = addRecipeInfo.description,
|
||||
recipeYield = addRecipeInfo.recipeYield,
|
||||
recipeInstructions = addRecipeInfo.recipeInstructions.map { it.text },
|
||||
recipeIngredients = addRecipeInfo.recipeIngredient.map { it.note },
|
||||
isRecipePublic = addRecipeInfo.settings.public,
|
||||
areCommentsDisabled = addRecipeInfo.settings.disableComments,
|
||||
)
|
||||
|
||||
|
||||
override fun toVersionInfo(versionResponseV1: VersionResponseV1) =
|
||||
VersionInfo(versionResponseV1.version)
|
||||
|
||||
override fun toFullRecipeInfo(getRecipeResponseV1: GetRecipeResponseV1) = FullRecipeInfo(
|
||||
remoteId = getRecipeResponseV1.remoteId,
|
||||
name = getRecipeResponseV1.name,
|
||||
recipeYield = getRecipeResponseV1.recipeYield,
|
||||
recipeIngredients = getRecipeResponseV1.recipeIngredients.map { toRecipeIngredientInfo(it) },
|
||||
recipeInstructions = getRecipeResponseV1.recipeInstructions.map { toRecipeInstructionInfo(it) },
|
||||
settings = toRecipeSettingsInfo(getRecipeResponseV1.settings),
|
||||
)
|
||||
|
||||
override fun toRecipeSettingsInfo(getRecipeSettingsResponseV1: GetRecipeSettingsResponseV1?) =
|
||||
RecipeSettingsInfo(
|
||||
disableAmounts = getRecipeSettingsResponseV1?.disableAmount ?: true,
|
||||
)
|
||||
|
||||
override fun toRecipeIngredientInfo(getRecipeIngredientResponseV1: GetRecipeIngredientResponseV1) =
|
||||
RecipeIngredientInfo(
|
||||
note = getRecipeIngredientResponseV1.note,
|
||||
unit = getRecipeIngredientResponseV1.unit?.name,
|
||||
food = getRecipeIngredientResponseV1.food?.name,
|
||||
quantity = getRecipeIngredientResponseV1.quantity,
|
||||
title = getRecipeIngredientResponseV1.title,
|
||||
)
|
||||
|
||||
override fun toRecipeInstructionInfo(getRecipeInstructionResponseV1: GetRecipeInstructionResponseV1) =
|
||||
RecipeInstructionInfo(
|
||||
text = getRecipeInstructionResponseV1.text
|
||||
)
|
||||
|
||||
override fun toV1CreateRequest(addRecipeInfo: AddRecipeInfo) = CreateRecipeRequestV1(
|
||||
name = addRecipeInfo.name,
|
||||
)
|
||||
|
||||
override fun toV1UpdateRequest(addRecipeInfo: AddRecipeInfo) = UpdateRecipeRequestV1(
|
||||
description = addRecipeInfo.description,
|
||||
recipeYield = addRecipeInfo.recipeYield,
|
||||
recipeIngredient = addRecipeInfo.recipeIngredient.map { toV1Ingredient(it) },
|
||||
recipeInstructions = addRecipeInfo.recipeInstructions.map { toV1Instruction(it) },
|
||||
settings = toV1Settings(addRecipeInfo.settings),
|
||||
)
|
||||
|
||||
override fun toV1Settings(addRecipeSettingsInfo: AddRecipeSettingsInfo) = AddRecipeSettingsV1(
|
||||
disableComments = addRecipeSettingsInfo.disableComments,
|
||||
public = addRecipeSettingsInfo.public,
|
||||
)
|
||||
|
||||
override fun toV1Ingredient(addRecipeIngredientInfo: AddRecipeIngredientInfo) =
|
||||
AddRecipeIngredientV1(
|
||||
id = UUID.randomUUID().toString(),
|
||||
note = addRecipeIngredientInfo.note,
|
||||
)
|
||||
|
||||
override fun toV1Instruction(addRecipeInstructionInfo: AddRecipeInstructionInfo) =
|
||||
AddRecipeInstructionV1(
|
||||
id = UUID.randomUUID().toString(),
|
||||
text = addRecipeInstructionInfo.text,
|
||||
ingredientReferences = emptyList(),
|
||||
)
|
||||
|
||||
override fun toV1Request(parseRecipeURLInfo: ParseRecipeURLInfo) = ParseRecipeURLRequestV1(
|
||||
url = parseRecipeURLInfo.url,
|
||||
includeTags = parseRecipeURLInfo.includeTags,
|
||||
)
|
||||
|
||||
override fun toFullShoppingListInfo(getShoppingListResponseV1: GetShoppingListResponseV1): FullShoppingListInfo {
|
||||
val recipes = getShoppingListResponseV1.recipeReferences.groupBy { it.recipeId }
|
||||
return FullShoppingListInfo(
|
||||
id = getShoppingListResponseV1.id,
|
||||
name = getShoppingListResponseV1.name,
|
||||
items = getShoppingListResponseV1.listItems.map { toShoppingListItemInfo(it, recipes) },
|
||||
)
|
||||
}
|
||||
|
||||
override fun toShoppingListItemInfo(
|
||||
getShoppingListItemResponseV1: GetShoppingListItemResponseV1,
|
||||
recipes: Map<String, List<GetShoppingListItemRecipeReferenceFullResponseV1>>
|
||||
): ShoppingListItemInfo = ShoppingListItemInfo(
|
||||
shoppingListId = getShoppingListItemResponseV1.shoppingListId,
|
||||
id = getShoppingListItemResponseV1.id,
|
||||
checked = getShoppingListItemResponseV1.checked,
|
||||
position = getShoppingListItemResponseV1.position,
|
||||
isFood = getShoppingListItemResponseV1.isFood,
|
||||
note = getShoppingListItemResponseV1.note,
|
||||
quantity = getShoppingListItemResponseV1.quantity,
|
||||
unit = getShoppingListItemResponseV1.unit?.name.orEmpty(),
|
||||
food = getShoppingListItemResponseV1.food?.name.orEmpty(),
|
||||
recipeReferences = getShoppingListItemResponseV1.recipeReferences.map { it.recipeId }
|
||||
.mapNotNull { recipes[it] }.flatten().map { toShoppingListItemRecipeReferenceInfo(it) },
|
||||
)
|
||||
|
||||
override fun toShoppingListItemRecipeReferenceInfo(
|
||||
getShoppingListItemRecipeReferenceFullResponseV1: GetShoppingListItemRecipeReferenceFullResponseV1
|
||||
) = ShoppingListItemRecipeReferenceInfo(
|
||||
recipeId = getShoppingListItemRecipeReferenceFullResponseV1.recipeId,
|
||||
recipeQuantity = getShoppingListItemRecipeReferenceFullResponseV1.recipeQuantity,
|
||||
id = getShoppingListItemRecipeReferenceFullResponseV1.id,
|
||||
shoppingListId = getShoppingListItemRecipeReferenceFullResponseV1.shoppingListId,
|
||||
recipe = toFullRecipeInfo(getShoppingListItemRecipeReferenceFullResponseV1.recipe),
|
||||
)
|
||||
|
||||
override fun toShoppingListsInfo(getShoppingListsResponseV1: GetShoppingListsResponseV1) =
|
||||
ShoppingListsInfo(
|
||||
page = getShoppingListsResponseV1.page,
|
||||
perPage = getShoppingListsResponseV1.perPage,
|
||||
totalPages = getShoppingListsResponseV1.totalPages,
|
||||
totalItems = getShoppingListsResponseV1.total,
|
||||
items = getShoppingListsResponseV1.items.map { toShoppingListInfo(it) },
|
||||
)
|
||||
|
||||
override fun toShoppingListInfo(getShoppingListsSummaryResponseV1: GetShoppingListsSummaryResponseV1) =
|
||||
ShoppingListInfo(
|
||||
name = getShoppingListsSummaryResponseV1.name.orEmpty(),
|
||||
id = getShoppingListsSummaryResponseV1.id,
|
||||
)
|
||||
|
||||
override fun toRecipeSummaryInfo(getRecipeSummaryResponseV1: GetRecipeSummaryResponseV1) =
|
||||
RecipeSummaryInfo(
|
||||
remoteId = getRecipeSummaryResponseV1.remoteId,
|
||||
name = getRecipeSummaryResponseV1.name,
|
||||
slug = getRecipeSummaryResponseV1.slug,
|
||||
description = getRecipeSummaryResponseV1.description,
|
||||
dateAdded = getRecipeSummaryResponseV1.dateAdded,
|
||||
dateUpdated = getRecipeSummaryResponseV1.dateUpdated,
|
||||
imageId = getRecipeSummaryResponseV1.remoteId,
|
||||
)
|
||||
|
||||
|
||||
override fun toRecipeSummaryInfo(getRecipeSummaryResponseV0: GetRecipeSummaryResponseV0) =
|
||||
RecipeSummaryInfo(
|
||||
remoteId = getRecipeSummaryResponseV0.remoteId.toString(),
|
||||
name = getRecipeSummaryResponseV0.name,
|
||||
slug = getRecipeSummaryResponseV0.slug,
|
||||
description = getRecipeSummaryResponseV0.description,
|
||||
dateAdded = getRecipeSummaryResponseV0.dateAdded,
|
||||
dateUpdated = getRecipeSummaryResponseV0.dateUpdated,
|
||||
imageId = getRecipeSummaryResponseV0.slug,
|
||||
)
|
||||
|
||||
override fun toVersionInfo(versionResponseV0: VersionResponseV0) =
|
||||
VersionInfo(versionResponseV0.version)
|
||||
|
||||
override fun toFullRecipeInfo(getRecipeResponseV0: GetRecipeResponseV0) = FullRecipeInfo(
|
||||
remoteId = getRecipeResponseV0.remoteId.toString(),
|
||||
name = getRecipeResponseV0.name,
|
||||
recipeYield = getRecipeResponseV0.recipeYield,
|
||||
recipeIngredients = getRecipeResponseV0.recipeIngredients.map { toRecipeIngredientInfo(it) },
|
||||
recipeInstructions = getRecipeResponseV0.recipeInstructions.map { toRecipeInstructionInfo(it) },
|
||||
settings = RecipeSettingsInfo(disableAmounts = true)
|
||||
)
|
||||
|
||||
override fun toRecipeIngredientInfo(getRecipeIngredientResponseV0: GetRecipeIngredientResponseV0) =
|
||||
RecipeIngredientInfo(
|
||||
note = getRecipeIngredientResponseV0.note,
|
||||
unit = null,
|
||||
food = null,
|
||||
quantity = 1.0,
|
||||
title = null,
|
||||
)
|
||||
|
||||
override fun toRecipeInstructionInfo(getRecipeInstructionResponseV0: GetRecipeInstructionResponseV0) =
|
||||
RecipeInstructionInfo(
|
||||
text = getRecipeInstructionResponseV0.text
|
||||
)
|
||||
|
||||
override fun toV0Request(addRecipeInfo: AddRecipeInfo) = AddRecipeRequestV0(
|
||||
name = addRecipeInfo.name,
|
||||
description = addRecipeInfo.description,
|
||||
recipeYield = addRecipeInfo.recipeYield,
|
||||
recipeIngredient = addRecipeInfo.recipeIngredient.map { toV0Ingredient(it) },
|
||||
recipeInstructions = addRecipeInfo.recipeInstructions.map { toV0Instruction(it) },
|
||||
settings = toV0Settings(addRecipeInfo.settings),
|
||||
)
|
||||
|
||||
override fun toV0Settings(addRecipeSettingsInfo: AddRecipeSettingsInfo) = AddRecipeSettingsV0(
|
||||
disableComments = addRecipeSettingsInfo.disableComments,
|
||||
public = addRecipeSettingsInfo.public,
|
||||
)
|
||||
|
||||
override fun toV0Ingredient(addRecipeIngredientInfo: AddRecipeIngredientInfo) =
|
||||
AddRecipeIngredientV0(
|
||||
note = addRecipeIngredientInfo.note,
|
||||
)
|
||||
|
||||
override fun toV0Instruction(addRecipeInstructionInfo: AddRecipeInstructionInfo) =
|
||||
AddRecipeInstructionV0(
|
||||
text = addRecipeInstructionInfo.text,
|
||||
)
|
||||
|
||||
override fun toV0Request(parseRecipeURLInfo: ParseRecipeURLInfo) = ParseRecipeURLRequestV0(
|
||||
url = parseRecipeURLInfo.url,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package gq.kirmanak.mealient.model_mapper
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface ModelMapperModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindModelMapper(impl: ModelMapperImpl): ModelMapper
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package gq.kirmanak.mealient.model_mapper
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import gq.kirmanak.mealient.database.CAKE_RECIPE_ENTITY
|
||||
import gq.kirmanak.mealient.database.CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY
|
||||
import gq.kirmanak.mealient.database.MIX_CAKE_RECIPE_INSTRUCTION_ENTITY
|
||||
import gq.kirmanak.mealient.database.PORRIDGE_RECIPE_SUMMARY_ENTITY
|
||||
import gq.kirmanak.mealient.datasource_test.CAKE_FULL_RECIPE_INFO
|
||||
import gq.kirmanak.mealient.datasource_test.MILK_RECIPE_INGREDIENT_INFO
|
||||
import gq.kirmanak.mealient.datasource_test.MILK_RECIPE_INGREDIENT_RESPONSE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.MILK_RECIPE_INGREDIENT_RESPONSE_V1
|
||||
import gq.kirmanak.mealient.datasource_test.MIX_INSTRUCTION
|
||||
import gq.kirmanak.mealient.datasource_test.MIX_RECIPE_INSTRUCTION_INFO
|
||||
import gq.kirmanak.mealient.datasource_test.MIX_RECIPE_INSTRUCTION_RESPONSE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.MIX_RECIPE_INSTRUCTION_RESPONSE_V1
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_ADD_RECIPE_INFO
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_ADD_RECIPE_REQUEST_V0
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_CREATE_RECIPE_REQUEST_V1
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_FULL_RECIPE_INFO
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_RECIPE_RESPONSE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_RECIPE_RESPONSE_V1
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_RECIPE_SUMMARY_RESPONSE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_RECIPE_SUMMARY_RESPONSE_V1
|
||||
import gq.kirmanak.mealient.datasource_test.PORRIDGE_UPDATE_RECIPE_REQUEST_V1
|
||||
import gq.kirmanak.mealient.datasource_test.RECIPE_SUMMARY_PORRIDGE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.RECIPE_SUMMARY_PORRIDGE_V1
|
||||
import gq.kirmanak.mealient.datasource_test.SUGAR_INGREDIENT
|
||||
import gq.kirmanak.mealient.datasource_test.VERSION_INFO_V0
|
||||
import gq.kirmanak.mealient.datasource_test.VERSION_INFO_V1
|
||||
import gq.kirmanak.mealient.datasource_test.VERSION_RESPONSE_V0
|
||||
import gq.kirmanak.mealient.datasource_test.VERSION_RESPONSE_V1
|
||||
import gq.kirmanak.mealient.datastore_test.PORRIDGE_RECIPE_DRAFT
|
||||
import gq.kirmanak.mealient.test.BaseUnitTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class ModelMappingsTest : BaseUnitTest() {
|
||||
|
||||
private lateinit var subject: ModelMapper
|
||||
|
||||
@Before
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
subject = ModelMapperImpl()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when toAddRecipeRequest then fills fields correctly`() {
|
||||
assertThat(subject.toAddRecipeInfo(PORRIDGE_RECIPE_DRAFT)).isEqualTo(
|
||||
PORRIDGE_ADD_RECIPE_INFO
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when toDraft then fills fields correctly`() {
|
||||
assertThat(subject.toDraft(PORRIDGE_ADD_RECIPE_INFO)).isEqualTo(PORRIDGE_RECIPE_DRAFT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when full recipe info to entity expect correct entity`() {
|
||||
assertThat(subject.toRecipeEntity(CAKE_FULL_RECIPE_INFO)).isEqualTo(CAKE_RECIPE_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when ingredient info to entity expect correct entity`() {
|
||||
val actual = subject.toRecipeIngredientEntity(SUGAR_INGREDIENT, "1")
|
||||
assertThat(actual).isEqualTo(CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when instruction info to entity expect correct entity`() {
|
||||
val actual = subject.toRecipeInstructionEntity(MIX_INSTRUCTION, "1")
|
||||
assertThat(actual).isEqualTo(MIX_CAKE_RECIPE_INSTRUCTION_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when summary v0 to info expect correct info`() {
|
||||
val actual = subject.toRecipeSummaryInfo(PORRIDGE_RECIPE_SUMMARY_RESPONSE_V0)
|
||||
assertThat(actual).isEqualTo(RECIPE_SUMMARY_PORRIDGE_V0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when summary v1 to info expect correct info`() {
|
||||
val actual = subject.toRecipeSummaryInfo(PORRIDGE_RECIPE_SUMMARY_RESPONSE_V1)
|
||||
assertThat(actual).isEqualTo(RECIPE_SUMMARY_PORRIDGE_V1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when summary info to entity expect correct entity`() {
|
||||
val actual = subject.toRecipeSummaryEntity(RECIPE_SUMMARY_PORRIDGE_V0, isFavorite = false)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_RECIPE_SUMMARY_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when version response v0 to info expect correct info`() {
|
||||
assertThat(subject.toVersionInfo(VERSION_RESPONSE_V0)).isEqualTo(VERSION_INFO_V0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when version response v1 to info expect correct info`() {
|
||||
assertThat(subject.toVersionInfo(VERSION_RESPONSE_V1)).isEqualTo(VERSION_INFO_V1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe ingredient response v0 to info expect correct info`() {
|
||||
val actual = subject.toRecipeIngredientInfo(MILK_RECIPE_INGREDIENT_RESPONSE_V0)
|
||||
assertThat(actual).isEqualTo(MILK_RECIPE_INGREDIENT_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe ingredient response v1 to info expect correct info`() {
|
||||
val actual = subject.toRecipeIngredientInfo(MILK_RECIPE_INGREDIENT_RESPONSE_V1)
|
||||
assertThat(actual).isEqualTo(MILK_RECIPE_INGREDIENT_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe instruction response v0 to info expect correct info`() {
|
||||
val actual = subject.toRecipeInstructionInfo(MIX_RECIPE_INSTRUCTION_RESPONSE_V0)
|
||||
assertThat(actual).isEqualTo(MIX_RECIPE_INSTRUCTION_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe instruction response v1 to info expect correct info`() {
|
||||
val actual = subject.toRecipeInstructionInfo(MIX_RECIPE_INSTRUCTION_RESPONSE_V1)
|
||||
assertThat(actual).isEqualTo(MIX_RECIPE_INSTRUCTION_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe response v0 to info expect correct info`() {
|
||||
val actual = subject.toFullRecipeInfo(PORRIDGE_RECIPE_RESPONSE_V0)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_FULL_RECIPE_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recipe response v1 to info expect correct info`() {
|
||||
val actual = subject.toFullRecipeInfo(PORRIDGE_RECIPE_RESPONSE_V1)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_FULL_RECIPE_INFO)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when add recipe info to request v0 expect correct request`() {
|
||||
val actual = subject.toV0Request(PORRIDGE_ADD_RECIPE_INFO)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_ADD_RECIPE_REQUEST_V0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when add recipe info to create request v1 expect correct request`() {
|
||||
val actual = subject.toV1CreateRequest(PORRIDGE_ADD_RECIPE_INFO)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_CREATE_RECIPE_REQUEST_V1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when add recipe info to update request v1 expect correct request`() {
|
||||
val actual = subject.toV1UpdateRequest(PORRIDGE_ADD_RECIPE_INFO)
|
||||
assertThat(actual).isEqualTo(PORRIDGE_UPDATE_RECIPE_REQUEST_V1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user