diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoFragment.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoFragment.kt index 4c33d71..1027e7b 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoFragment.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoFragment.kt @@ -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() - private val viewModel by viewModels() + private val binding by viewBinding(FragmentRecipeInfoBinding::bind) + private val arguments by navArgs() + private val viewModel by viewModels() - 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 } -} \ No newline at end of file + } +} diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoListsVisibility.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoListsVisibility.kt new file mode 100644 index 0000000..84bee8d --- /dev/null +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoListsVisibility.kt @@ -0,0 +1,6 @@ +package gq.kirmanak.mealient.ui.recipes.info + +data class RecipeInfoListsVisibility( + val areIngredientsVisible: Boolean = false, + val areInstructionsVisible: Boolean = false, +) diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoViewModel.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoViewModel.kt index 4355ee7..7195021 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoViewModel.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInfoViewModel.kt @@ -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() - val recipeInfo: LiveData = _recipeInfo - val recipeIngredientsAdapter = RecipeIngredientsAdapter() - val recipeInstructionsAdapter = RecipeInstructionsAdapter() + val recipeInfo: LiveData by ::_recipeInfo + private val _listsVisibility = MutableLiveData(RecipeInfoListsVisibility()) + val listsVisibility: LiveData 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") } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeIngredientsAdapter.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeIngredientsAdapter.kt index 1d6215f..2ca4939 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeIngredientsAdapter.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeIngredientsAdapter.kt @@ -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(RecipeIngredientDiffCallback) { class RecipeIngredientViewHolder( diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInstructionsAdapter.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInstructionsAdapter.kt index b84cd1b..6f32f87 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInstructionsAdapter.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/info/RecipeInstructionsAdapter.kt @@ -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(RecipeInstructionDiffCallback) { private object RecipeInstructionDiffCallback : diff --git a/app/src/main/res/layout/fragment_recipe_info.xml b/app/src/main/res/layout/fragment_recipe_info.xml index 780695f..620b25e 100644 --- a/app/src/main/res/layout/fragment_recipe_info.xml +++ b/app/src/main/res/layout/fragment_recipe_info.xml @@ -109,6 +109,13 @@ + +