Implement hiding ingredients and instructions
This commit is contained in:
@@ -5,7 +5,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
@@ -15,50 +15,62 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import gq.kirmanak.mealient.R
|
||||
import gq.kirmanak.mealient.databinding.FragmentRecipeInfoBinding
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class RecipeInfoFragment : BottomSheetDialogFragment() {
|
||||
private val binding by viewBinding(FragmentRecipeInfoBinding::bind)
|
||||
private val arguments by navArgs<RecipeInfoFragmentArgs>()
|
||||
private val viewModel by viewModels<RecipeInfoViewModel>()
|
||||
private val binding by viewBinding(FragmentRecipeInfoBinding::bind)
|
||||
private val arguments by navArgs<RecipeInfoFragmentArgs>()
|
||||
private val viewModel by viewModels<RecipeInfoViewModel>()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
Timber.v("onCreateView() called with: inflater = $inflater, container = $container, savedInstanceState = $savedInstanceState")
|
||||
return FragmentRecipeInfoBinding.inflate(inflater, container, false).root
|
||||
@Inject
|
||||
lateinit var ingredientsAdapter: RecipeIngredientsAdapter
|
||||
|
||||
@Inject
|
||||
lateinit var instructionsAdapter: RecipeInstructionsAdapter
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
Timber.v("onCreateView() called")
|
||||
return FragmentRecipeInfoBinding.inflate(inflater, container, false).root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
Timber.v("onViewCreated() called")
|
||||
|
||||
binding.ingredientsList.adapter = ingredientsAdapter
|
||||
binding.instructionsList.adapter = instructionsAdapter
|
||||
|
||||
viewModel.loadRecipeImage(binding.image, arguments.recipeSlug)
|
||||
viewModel.loadRecipeInfo(arguments.recipeId, arguments.recipeSlug)
|
||||
|
||||
viewModel.recipeInfo.observe(viewLifecycleOwner) {
|
||||
Timber.d("onViewCreated: full info $it")
|
||||
binding.title.text = it.recipeSummaryEntity.name
|
||||
binding.description.text = it.recipeSummaryEntity.description
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
Timber.v("onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState")
|
||||
|
||||
binding.ingredientsList.adapter = viewModel.recipeIngredientsAdapter
|
||||
binding.instructionsList.adapter = viewModel.recipeInstructionsAdapter
|
||||
|
||||
viewModel.loadRecipeImage(binding.image, arguments.recipeSlug)
|
||||
viewModel.loadRecipeInfo(arguments.recipeId, arguments.recipeSlug)
|
||||
|
||||
viewModel.recipeInfo.observe(viewLifecycleOwner) {
|
||||
Timber.d("onViewCreated: full info $it")
|
||||
binding.title.text = it.recipeSummaryEntity.name
|
||||
binding.description.text = it.recipeSummaryEntity.description
|
||||
}
|
||||
(requireActivity() as? AppCompatActivity)?.supportActionBar?.title = null
|
||||
viewModel.listsVisibility.observe(viewLifecycleOwner) {
|
||||
Timber.d("onViewCreated: lists visibility $it")
|
||||
binding.ingredientsHolder.isVisible = it.areIngredientsVisible
|
||||
binding.instructionsGroup.isVisible = it.areInstructionsVisible
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
|
||||
BottomSheetDialog(requireContext(), R.style.NoShapeBottomSheetDialog)
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
|
||||
BottomSheetDialog(requireContext(), R.style.NoShapeBottomSheetDialog)
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
Timber.v("onDestroyView() called")
|
||||
// Prevent RV leaking through mObservers list in adapter
|
||||
with(binding) {
|
||||
ingredientsList.adapter = null
|
||||
instructionsList.adapter = null
|
||||
}
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
Timber.v("onDestroyView() called")
|
||||
// Prevent RV leaking through mObservers list in adapter
|
||||
with(binding) {
|
||||
ingredientsList.adapter = null
|
||||
instructionsList.adapter = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package gq.kirmanak.mealient.ui.recipes.info
|
||||
|
||||
data class RecipeInfoListsVisibility(
|
||||
val areIngredientsVisible: Boolean = false,
|
||||
val areInstructionsVisible: Boolean = false,
|
||||
)
|
||||
@@ -14,35 +14,44 @@ import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class RecipeInfoViewModel @Inject constructor(
|
||||
class RecipeInfoViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val recipeRepo: RecipeRepo,
|
||||
private val recipeImageLoader: RecipeImageLoader
|
||||
private val recipeImageLoader: RecipeImageLoader,
|
||||
private val recipeIngredientsAdapter: RecipeIngredientsAdapter,
|
||||
private val recipeInstructionsAdapter: RecipeInstructionsAdapter,
|
||||
) : ViewModel() {
|
||||
|
||||
private val _recipeInfo = MutableLiveData<FullRecipeInfo>()
|
||||
val recipeInfo: LiveData<FullRecipeInfo> = _recipeInfo
|
||||
val recipeIngredientsAdapter = RecipeIngredientsAdapter()
|
||||
val recipeInstructionsAdapter = RecipeInstructionsAdapter()
|
||||
val recipeInfo: LiveData<FullRecipeInfo> by ::_recipeInfo
|
||||
private val _listsVisibility = MutableLiveData(RecipeInfoListsVisibility())
|
||||
val listsVisibility: LiveData<RecipeInfoListsVisibility> by ::_listsVisibility
|
||||
|
||||
fun loadRecipeImage(view: ImageView, recipeSlug: String) {
|
||||
Timber.v("loadRecipeImage() called with: view = $view, recipeSlug = $recipeSlug")
|
||||
viewModelScope.launch {
|
||||
recipeImageLoader.loadRecipeImage(view, recipeSlug)
|
||||
}
|
||||
viewModelScope.launch { recipeImageLoader.loadRecipeImage(view, recipeSlug) }
|
||||
}
|
||||
|
||||
fun loadRecipeInfo(recipeId: Long, recipeSlug: String) {
|
||||
Timber.v("loadRecipeInfo() called with: recipeId = $recipeId, recipeSlug = $recipeSlug")
|
||||
_listsVisibility.value = RecipeInfoListsVisibility()
|
||||
recipeIngredientsAdapter.submitList(null)
|
||||
recipeInstructionsAdapter.submitList(null)
|
||||
viewModelScope.launch {
|
||||
runCatching {
|
||||
recipeRepo.loadRecipeInfo(recipeId, recipeSlug)
|
||||
}.onSuccess {
|
||||
Timber.d("loadRecipeInfo: received recipe info = $it")
|
||||
_recipeInfo.value = it
|
||||
recipeIngredientsAdapter.submitList(it.recipeIngredients)
|
||||
recipeInstructionsAdapter.submitList(it.recipeInstructions)
|
||||
}.onFailure {
|
||||
Timber.e(it, "loadRecipeInfo: can't load recipe info")
|
||||
}
|
||||
runCatching { recipeRepo.loadRecipeInfo(recipeId, recipeSlug) }
|
||||
.onSuccess {
|
||||
Timber.d("loadRecipeInfo: received recipe info = $it")
|
||||
_recipeInfo.value = it
|
||||
recipeIngredientsAdapter.submitList(it.recipeIngredients)
|
||||
recipeInstructionsAdapter.submitList(it.recipeInstructions)
|
||||
_listsVisibility.value =
|
||||
RecipeInfoListsVisibility(
|
||||
areIngredientsVisible = it.recipeIngredients.isNotEmpty(),
|
||||
areInstructionsVisible = it.recipeInstructions.isNotEmpty()
|
||||
)
|
||||
}
|
||||
.onFailure { Timber.e(it, "loadRecipeInfo: can't load recipe info") }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,11 @@ import gq.kirmanak.mealient.data.recipes.db.entity.RecipeIngredientEntity
|
||||
import gq.kirmanak.mealient.databinding.ViewHolderIngredientBinding
|
||||
import gq.kirmanak.mealient.ui.recipes.info.RecipeIngredientsAdapter.RecipeIngredientViewHolder
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
class RecipeIngredientsAdapter :
|
||||
@Singleton
|
||||
class RecipeIngredientsAdapter @Inject constructor() :
|
||||
ListAdapter<RecipeIngredientEntity, RecipeIngredientViewHolder>(RecipeIngredientDiffCallback) {
|
||||
|
||||
class RecipeIngredientViewHolder(
|
||||
|
||||
@@ -10,8 +10,11 @@ import gq.kirmanak.mealient.data.recipes.db.entity.RecipeInstructionEntity
|
||||
import gq.kirmanak.mealient.databinding.ViewHolderInstructionBinding
|
||||
import gq.kirmanak.mealient.ui.recipes.info.RecipeInstructionsAdapter.RecipeInstructionViewHolder
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
class RecipeInstructionsAdapter :
|
||||
@Singleton
|
||||
class RecipeInstructionsAdapter @Inject constructor() :
|
||||
ListAdapter<RecipeInstructionEntity, RecipeInstructionViewHolder>(RecipeInstructionDiffCallback) {
|
||||
|
||||
private object RecipeInstructionDiffCallback :
|
||||
|
||||
@@ -109,6 +109,13 @@
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/instructions_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="instructions_header,instructions_list" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/instructions_header"
|
||||
android:layout_width="0dp"
|
||||
|
||||
Reference in New Issue
Block a user