Hide/show favorite icon on sign-out/sign-in

This commit is contained in:
Kirill Kamakin
2022-12-14 22:14:28 +01:00
parent cd3931e147
commit a20694e7fd
5 changed files with 36 additions and 25 deletions

View File

@@ -2,7 +2,11 @@ package gq.kirmanak.mealient.ui.recipes
import android.view.View import android.view.View
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.scopes.FragmentScoped import dagger.hilt.android.scopes.FragmentScoped
import gq.kirmanak.mealient.R import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
@@ -10,25 +14,24 @@ import gq.kirmanak.mealient.databinding.ViewHolderRecipeBinding
import gq.kirmanak.mealient.extensions.resources import gq.kirmanak.mealient.extensions.resources
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.recipes.images.RecipeImageLoader import gq.kirmanak.mealient.ui.recipes.images.RecipeImageLoader
import javax.inject.Inject
class RecipeViewHolder private constructor( class RecipeViewHolder @AssistedInject constructor(
private val logger: Logger, private val logger: Logger,
private val binding: ViewHolderRecipeBinding, @Assisted private val binding: ViewHolderRecipeBinding,
private val recipeImageLoader: RecipeImageLoader, private val recipeImageLoader: RecipeImageLoader,
private val clickListener: (ClickEvent) -> Unit, @Assisted private val showFavoriteIcon: Boolean,
@Assisted private val clickListener: (ClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
@FragmentScoped @FragmentScoped
class Factory @Inject constructor( @AssistedFactory
private val recipeImageLoader: RecipeImageLoader, interface Factory {
private val logger: Logger,
) {
fun build( fun build(
showFavoriteIcon: Boolean,
binding: ViewHolderRecipeBinding, binding: ViewHolderRecipeBinding,
clickListener: (ClickEvent) -> Unit, clickListener: (ClickEvent) -> Unit,
) = RecipeViewHolder(logger, binding, recipeImageLoader, clickListener) ): RecipeViewHolder
} }
@@ -59,6 +62,7 @@ class RecipeViewHolder private constructor(
logger.d { "bind: item clicked $entity" } logger.d { "bind: item clicked $entity" }
clickListener(ClickEvent.RecipeClick(entity)) clickListener(ClickEvent.RecipeClick(entity))
} }
binding.favoriteIcon.isVisible = showFavoriteIcon
binding.favoriteIcon.setOnClickListener { binding.favoriteIcon.setOnClickListener {
clickListener(ClickEvent.FavoriteClick(entity)) clickListener(ClickEvent.FavoriteClick(entity))
} }

View File

@@ -55,7 +55,9 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
checkedMenuItemId = R.id.recipes_list checkedMenuItemId = R.id.recipes_list
) )
} }
setupRecipeAdapter() viewModel.showFavoriteIcon.observe(viewLifecycleOwner) { showFavoriteIcon ->
setupRecipeAdapter(showFavoriteIcon)
}
hideKeyboardOnScroll() hideKeyboardOnScroll()
} }
@@ -87,10 +89,10 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
return findNavController().currentDestination?.id != R.id.recipesListFragment return findNavController().currentDestination?.id != R.id.recipesListFragment
} }
private fun setupRecipeAdapter() { private fun setupRecipeAdapter(showFavoriteIcon: Boolean) {
logger.v { "setupRecipeAdapter() called" } logger.v { "setupRecipeAdapter() called" }
val recipesAdapter = recipePagingAdapterFactory.build { val recipesAdapter = recipePagingAdapterFactory.build(showFavoriteIcon) {
when (it) { when (it) {
is RecipeViewHolder.ClickEvent.FavoriteClick -> { is RecipeViewHolder.ClickEvent.FavoriteClick -> {
onFavoriteClick(it) onFavoriteClick(it)

View File

@@ -2,6 +2,7 @@ package gq.kirmanak.mealient.ui.recipes
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.liveData import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.cachedIn import androidx.paging.cachedIn
@@ -23,6 +24,7 @@ class RecipesListViewModel @Inject constructor(
) : ViewModel() { ) : ViewModel() {
val pagingData = recipeRepo.createPager().flow.cachedIn(viewModelScope) val pagingData = recipeRepo.createPager().flow.cachedIn(viewModelScope)
val showFavoriteIcon = authRepo.isAuthorizedFlow.asLiveData()
init { init {
authRepo.isAuthorizedFlow.valueUpdatesOnly().onEach { hasAuthorized -> authRepo.isAuthorizedFlow.valueUpdatesOnly().onEach { hasAuthorized ->
@@ -40,7 +42,6 @@ class RecipesListViewModel @Inject constructor(
} }
} }
// TODO hide favourite icons if not authorized
fun onFavoriteIconClick(recipeSummaryEntity: RecipeSummaryEntity) = liveData { fun onFavoriteIconClick(recipeSummaryEntity: RecipeSummaryEntity) = liveData {
logger.v { "onFavoriteIconClick() called with: recipeSummaryEntity = $recipeSummaryEntity" } logger.v { "onFavoriteIconClick() called with: recipeSummaryEntity = $recipeSummaryEntity" }
recipeRepo.updateIsRecipeFavorite( recipeRepo.updateIsRecipeFavorite(

View File

@@ -4,27 +4,29 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.paging.PagingDataAdapter import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.scopes.FragmentScoped import dagger.hilt.android.scopes.FragmentScoped
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.databinding.ViewHolderRecipeBinding import gq.kirmanak.mealient.databinding.ViewHolderRecipeBinding
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.logging.Logger
import javax.inject.Inject
class RecipesPagingAdapter private constructor( class RecipesPagingAdapter @AssistedInject constructor(
private val logger: Logger, private val logger: Logger,
private val recipeViewHolderFactory: RecipeViewHolder.Factory, private val recipeViewHolderFactory: RecipeViewHolder.Factory,
private val clickListener: (RecipeViewHolder.ClickEvent) -> Unit @Assisted private val showFavoriteIcon: Boolean,
@Assisted private val clickListener: (RecipeViewHolder.ClickEvent) -> Unit
) : PagingDataAdapter<RecipeSummaryEntity, RecipeViewHolder>(RecipeDiffCallback) { ) : PagingDataAdapter<RecipeSummaryEntity, RecipeViewHolder>(RecipeDiffCallback) {
@FragmentScoped @FragmentScoped
class Factory @Inject constructor( @AssistedFactory
private val logger: Logger, interface Factory {
private val recipeViewHolderFactory: RecipeViewHolder.Factory,
) {
fun build(clickListener: (RecipeViewHolder.ClickEvent) -> Unit) = RecipesPagingAdapter( fun build(
logger, recipeViewHolderFactory, clickListener showFavoriteIcon: Boolean,
) clickListener: (RecipeViewHolder.ClickEvent) -> Unit,
): RecipesPagingAdapter
} }
override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) { override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) {
@@ -37,7 +39,7 @@ class RecipesPagingAdapter private constructor(
logger.v { "onCreateViewHolder() called with: parent = $parent, viewType = $viewType" } logger.v { "onCreateViewHolder() called with: parent = $parent, viewType = $viewType" }
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
val binding = ViewHolderRecipeBinding.inflate(inflater, parent, false) val binding = ViewHolderRecipeBinding.inflate(inflater, parent, false)
return recipeViewHolderFactory.build(binding, clickListener) return recipeViewHolderFactory.build(showFavoriteIcon, binding, clickListener)
} }
private object RecipeDiffCallback : DiffUtil.ItemCallback<RecipeSummaryEntity>() { private object RecipeDiffCallback : DiffUtil.ItemCallback<RecipeSummaryEntity>() {

View File

@@ -40,6 +40,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/favorite_icon" app:layout_constraintTop_toBottomOf="@id/favorite_icon"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
app:layout_goneMarginTop="@dimen/margin_medium"
app:shapeAppearance="?shapeAppearanceCornerMedium" app:shapeAppearance="?shapeAppearanceCornerMedium"
tools:srcCompat="@drawable/placeholder_recipe" /> tools:srcCompat="@drawable/placeholder_recipe" />
@@ -52,6 +53,7 @@
app:layout_constraintBottom_toTopOf="@+id/image" app:layout_constraintBottom_toTopOf="@+id/image"
app:layout_constraintEnd_toEndOf="@id/image" app:layout_constraintEnd_toEndOf="@id/image"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/ic_favorite_unfilled" /> tools:srcCompat="@drawable/ic_favorite_unfilled"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>