Split loadRecipeInfo to refresh/load

This commit is contained in:
Kirill Kamakin
2022-11-06 13:46:45 +01:00
parent cc73f68751
commit 4ad3e7662e
8 changed files with 27 additions and 44 deletions

View File

@@ -9,7 +9,7 @@ interface RecipeRepo {
suspend fun clearLocalData() suspend fun clearLocalData()
suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeEntity suspend fun refreshRecipeInfo(recipeSlug: String): Result<Unit>
suspend fun loadRecipeInfoFromDb(recipeId: String, recipeSlug: String): FullRecipeEntity? suspend fun loadRecipeInfo(recipeId: String): FullRecipeEntity?
} }

View File

@@ -17,5 +17,5 @@ interface RecipeStorage {
suspend fun saveRecipeInfo(recipe: FullRecipeInfo) suspend fun saveRecipeInfo(recipe: FullRecipeInfo)
suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity?
} }

View File

@@ -74,11 +74,9 @@ class RecipeStorageImpl @Inject constructor(
} }
} }
override suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity { override suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity? {
logger.v { "queryRecipeInfo() called with: recipeId = $recipeId" } logger.v { "queryRecipeInfo() called with: recipeId = $recipeId" }
val fullRecipeInfo = checkNotNull(recipeDao.queryFullRecipeInfo(recipeId)) { val fullRecipeInfo = recipeDao.queryFullRecipeInfo(recipeId)
"Can't find recipe by id $recipeId in DB"
}
logger.v { "queryRecipeInfo() returned: $fullRecipeInfo" } logger.v { "queryRecipeInfo() returned: $fullRecipeInfo" }
return fullRecipeInfo return fullRecipeInfo
} }

View File

@@ -38,25 +38,19 @@ class RecipeRepoImpl @Inject constructor(
storage.clearAllLocalData() storage.clearAllLocalData()
} }
override suspend fun loadRecipeInfo(recipeId: String, recipeSlug: String): FullRecipeEntity { override suspend fun refreshRecipeInfo(recipeSlug: String): Result<Unit> {
logger.v { "loadRecipeInfo() called with: recipeId = $recipeId, recipeSlug = $recipeSlug" } logger.v { "refreshRecipeInfo() called with: recipeSlug = $recipeSlug" }
return runCatchingExceptCancel {
runCatchingExceptCancel {
storage.saveRecipeInfo(dataSource.requestRecipeInfo(recipeSlug)) storage.saveRecipeInfo(dataSource.requestRecipeInfo(recipeSlug))
}.onFailure { }.onFailure {
logger.e(it) { "loadRecipeInfo: can't update full recipe info" } logger.e(it) { "loadRecipeInfo: can't update full recipe info" }
} }
return storage.queryRecipeInfo(recipeId)
} }
override suspend fun loadRecipeInfoFromDb( override suspend fun loadRecipeInfo(recipeId: String): FullRecipeEntity? {
recipeId: String, logger.v { "loadRecipeInfo() called with: recipeId = $recipeId" }
recipeSlug: String val recipeInfo = storage.queryRecipeInfo(recipeId)
): FullRecipeEntity? { logger.v { "loadRecipeInfo() returned: $recipeInfo" }
logger.v { "loadRecipeInfoFromDb() called with: recipeId = $recipeId, recipeSlug = $recipeSlug" } return recipeInfo
return runCatchingExceptCancel { storage.queryRecipeInfo(recipeId) }
.onFailure { logger.e(it) { "loadRecipeInfoFromDb failed" } }
.getOrNull()
} }
} }

View File

@@ -5,9 +5,6 @@ import androidx.paging.cachedIn
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealient.data.auth.AuthRepo import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.recipes.RecipeRepo import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
import gq.kirmanak.mealient.extensions.valueUpdatesOnly import gq.kirmanak.mealient.extensions.valueUpdatesOnly
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.logging.Logger
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
@@ -38,12 +35,12 @@ class RecipeViewModel @Inject constructor(
_isAuthorized.postValue(null) _isAuthorized.postValue(null)
} }
fun loadRecipeInfo( fun refreshRecipeInfo(recipeSlug: String): LiveData<Result<Unit>> {
summaryEntity: RecipeSummaryEntity logger.v { "refreshRecipeInfo called with: recipeSlug = $recipeSlug" }
): LiveData<Result<FullRecipeEntity>> = liveData { return liveData {
val result = runCatchingExceptCancel { val result = recipeRepo.refreshRecipeInfo(recipeSlug)
recipeRepo.loadRecipeInfo(summaryEntity.remoteId, summaryEntity.slug) logger.v { "refreshRecipeInfo: emitting $result" }
emit(result)
} }
emit(result)
} }
} }

View File

@@ -54,23 +54,20 @@ class RecipesFragment : Fragment(R.layout.fragment_recipes) {
setupRecipeAdapter() setupRecipeAdapter()
} }
private fun navigateToRecipeInfo(recipeSummaryEntity: RecipeSummaryEntity) { private fun navigateToRecipeInfo(id: String) {
logger.v { "navigateToRecipeInfo() called with: recipeSummaryEntity = $recipeSummaryEntity" } logger.v { "navigateToRecipeInfo() called with: id = $id" }
findNavController().navigate( val directions = RecipesFragmentDirections.actionRecipesFragmentToRecipeInfoFragment(id)
RecipesFragmentDirections.actionRecipesFragmentToRecipeInfoFragment( findNavController().navigate(directions)
recipeSlug = recipeSummaryEntity.slug, recipeId = recipeSummaryEntity.remoteId
)
)
} }
private fun onRecipeClicked(recipe: RecipeSummaryEntity) { private fun onRecipeClicked(recipe: RecipeSummaryEntity) {
logger.d { "onRecipeClicked() called with: recipe = $recipe" } logger.v { "onRecipeClicked() called with: recipe = $recipe" }
if (ignoreRecipeClicks) return if (ignoreRecipeClicks) return
binding.progress.isVisible = true binding.progress.isVisible = true
ignoreRecipeClicks = true // TODO doesn't really work ignoreRecipeClicks = true // TODO doesn't really work
viewModel.loadRecipeInfo(recipe).observeOnce(viewLifecycleOwner) { result -> viewModel.refreshRecipeInfo(recipe.slug).observeOnce(viewLifecycleOwner) { result ->
binding.progress.isVisible = false binding.progress.isVisible = false
if (result.isSuccess) navigateToRecipeInfo(recipe) if (result.isSuccess) navigateToRecipeInfo(recipe.remoteId)
ignoreRecipeClicks = false ignoreRecipeClicks = false
} }
} }

View File

@@ -20,7 +20,7 @@ class RecipeInfoViewModel @Inject constructor(
val uiState: LiveData<RecipeInfoUiState> = liveData { val uiState: LiveData<RecipeInfoUiState> = liveData {
logger.v { "Initializing UI state with args = $args" } logger.v { "Initializing UI state with args = $args" }
val state = recipeRepo.loadRecipeInfoFromDb(args.recipeId, args.recipeSlug)?.let { val state = recipeRepo.loadRecipeInfo(args.recipeId)?.let {
RecipeInfoUiState( RecipeInfoUiState(
areIngredientsVisible = it.recipeIngredients.isNotEmpty(), areIngredientsVisible = it.recipeIngredients.isNotEmpty(),
areInstructionsVisible = it.recipeInstructions.isNotEmpty(), areInstructionsVisible = it.recipeInstructions.isNotEmpty(),

View File

@@ -31,9 +31,6 @@
android:name="gq.kirmanak.mealient.ui.recipes.info.RecipeInfoFragment" android:name="gq.kirmanak.mealient.ui.recipes.info.RecipeInfoFragment"
android:label="RecipeInfoFragment" android:label="RecipeInfoFragment"
tools:layout="@layout/fragment_recipe_info"> tools:layout="@layout/fragment_recipe_info">
<argument
android:name="recipe_slug"
app:argType="string" />
<argument <argument
android:name="recipe_id" android:name="recipe_id"
app:argType="string" /> app:argType="string" />