Update favorite status on icon click

This commit is contained in:
Kirill Kamakin
2022-12-13 20:14:16 +01:00
parent 3eb99206e8
commit 2fa43f57b7
16 changed files with 170 additions and 21 deletions

View File

@@ -3,6 +3,7 @@ package gq.kirmanak.mealient.ui.recipes
import android.view.View
import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.scopes.FragmentScoped
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.databinding.ViewHolderRecipeBinding
@@ -10,28 +11,41 @@ import gq.kirmanak.mealient.extensions.resources
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.recipes.images.RecipeImageLoader
import javax.inject.Inject
import javax.inject.Singleton
class RecipeViewHolder private constructor(
private val logger: Logger,
private val binding: ViewHolderRecipeBinding,
private val recipeImageLoader: RecipeImageLoader,
private val clickListener: (RecipeSummaryEntity) -> Unit,
private val clickListener: (ClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root) {
@Singleton
@FragmentScoped
class Factory @Inject constructor(
private val recipeImageLoader: RecipeImageLoader,
private val logger: Logger,
) {
fun build(
recipeImageLoader: RecipeImageLoader,
binding: ViewHolderRecipeBinding,
clickListener: (RecipeSummaryEntity) -> Unit,
clickListener: (ClickEvent) -> Unit,
) = RecipeViewHolder(logger, binding, recipeImageLoader, clickListener)
}
sealed class ClickEvent {
abstract val recipeSummaryEntity: RecipeSummaryEntity
data class FavoriteClick(
override val recipeSummaryEntity: RecipeSummaryEntity
) : ClickEvent()
data class RecipeClick(
override val recipeSummaryEntity: RecipeSummaryEntity
) : ClickEvent()
}
private val loadingPlaceholder by lazy {
binding.resources.getString(R.string.view_holder_recipe_text_placeholder)
}
@@ -43,7 +57,10 @@ class RecipeViewHolder private constructor(
item?.let { entity ->
binding.root.setOnClickListener {
logger.d { "bind: item clicked $entity" }
clickListener(entity)
clickListener(ClickEvent.RecipeClick(entity))
}
binding.favoriteIcon.setOnClickListener {
clickListener(ClickEvent.FavoriteClick(entity))
}
binding.favoriteIcon.setImageResource(
if (item.isFavorite) {

View File

@@ -90,7 +90,16 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
private fun setupRecipeAdapter() {
logger.v { "setupRecipeAdapter() called" }
val recipesAdapter = recipePagingAdapterFactory.build { onRecipeClicked(it) }
val recipesAdapter = recipePagingAdapterFactory.build {
when (it) {
is RecipeViewHolder.ClickEvent.FavoriteClick -> {
viewModel.onFavoriteIconClick(it.recipeSummaryEntity)
}
is RecipeViewHolder.ClickEvent.RecipeClick -> {
onRecipeClicked(it.recipeSummaryEntity)
}
}
}
with(binding.recipes) {
adapter = recipesAdapter

View File

@@ -8,10 +8,12 @@ import androidx.paging.cachedIn
import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.extensions.valueUpdatesOnly
import gq.kirmanak.mealient.logging.Logger
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
@@ -38,4 +40,15 @@ class RecipesListViewModel @Inject constructor(
emit(result)
}
}
fun onFavoriteIconClick(recipeSummaryEntity: RecipeSummaryEntity) {
logger.v { "onFavoriteIconClick() called with: recipeSummaryEntity = $recipeSummaryEntity" }
viewModelScope.launch {
if (recipeSummaryEntity.isFavorite) {
recipeRepo.removeFavoriteRecipe(recipeSummaryEntity.slug)
} else {
recipeRepo.addFavoriteRecipe(recipeSummaryEntity.slug)
}
}
}
}

View File

@@ -8,28 +8,22 @@ import dagger.hilt.android.scopes.FragmentScoped
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.databinding.ViewHolderRecipeBinding
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.recipes.images.RecipeImageLoader
import javax.inject.Inject
class RecipesPagingAdapter private constructor(
private val logger: Logger,
private val recipeImageLoader: RecipeImageLoader,
private val recipeViewHolderFactory: RecipeViewHolder.Factory,
private val clickListener: (RecipeSummaryEntity) -> Unit
private val clickListener: (RecipeViewHolder.ClickEvent) -> Unit
) : PagingDataAdapter<RecipeSummaryEntity, RecipeViewHolder>(RecipeDiffCallback) {
@FragmentScoped
class Factory @Inject constructor(
private val logger: Logger,
private val recipeViewHolderFactory: RecipeViewHolder.Factory,
private val recipeImageLoader: RecipeImageLoader,
) {
fun build(clickListener: (RecipeSummaryEntity) -> Unit) = RecipesPagingAdapter(
logger,
recipeImageLoader,
recipeViewHolderFactory,
clickListener
fun build(clickListener: (RecipeViewHolder.ClickEvent) -> Unit) = RecipesPagingAdapter(
logger, recipeViewHolderFactory, clickListener
)
}
@@ -43,18 +37,16 @@ class RecipesPagingAdapter private constructor(
logger.v { "onCreateViewHolder() called with: parent = $parent, viewType = $viewType" }
val inflater = LayoutInflater.from(parent.context)
val binding = ViewHolderRecipeBinding.inflate(inflater, parent, false)
return recipeViewHolderFactory.build(recipeImageLoader, binding, clickListener)
return recipeViewHolderFactory.build(binding, clickListener)
}
private object RecipeDiffCallback : DiffUtil.ItemCallback<RecipeSummaryEntity>() {
override fun areItemsTheSame(
oldItem: RecipeSummaryEntity,
newItem: RecipeSummaryEntity
oldItem: RecipeSummaryEntity, newItem: RecipeSummaryEntity
): Boolean = oldItem.remoteId == newItem.remoteId
override fun areContentsTheSame(
oldItem: RecipeSummaryEntity,
newItem: RecipeSummaryEntity
oldItem: RecipeSummaryEntity, newItem: RecipeSummaryEntity
): Boolean = oldItem.name == newItem.name && oldItem.slug == newItem.slug
}
}