Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@ dependencies {
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
testImplementation(libs.kotlin.coroutines.test)
implementation (libs.glide)
annotationProcessor (libs.compiler)
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/kotlin/ru/otus/cookbook/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ru.otus.cookbook

import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import ru.otus.cookbook.databinding.ActivityMainBinding

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ru.otus.cookbook.cook_recycler_view

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import ru.otus.cookbook.R
import ru.otus.cookbook.data.RecipeListItem

class CategoryViewHolder(private val categoryView: View) : RecyclerView.ViewHolder(categoryView) {
private val categoryText: TextView by lazy { categoryView.findViewById(R.id.categoryText) }

fun bind(categoryData: RecipeListItem.CategoryItem) {
categoryText.text = categoryData.name
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package ru.otus.cookbook.cook_recycler_view

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ru.otus.cookbook.R
import ru.otus.cookbook.data.RecipeListItem

class RecipeAdapter : ListAdapter<RecipeListItem, RecyclerView.ViewHolder>(RecipeDiffutils()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {

return when (viewType) {
ViewType.CATEGORY.id -> {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.vh_recipe_category, parent, false)
CategoryViewHolder(view)
}

ViewType.RECIPE.id -> {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.vh_recipe_item, parent, false)
RecipeViewHolder(view)
}

else -> throw IllegalArgumentException("wrong type of view")
}
}

override fun getItemViewType(position: Int): Int {
return when (currentList[position]) {
is RecipeListItem.CategoryItem -> ViewType.CATEGORY.id
is RecipeListItem.RecipeItem -> ViewType.RECIPE.id
else -> -1
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

when (val item = currentList.getOrNull(position)) {
is RecipeListItem.CategoryItem -> {
(holder as CategoryViewHolder).bind(item)
}

is RecipeListItem.RecipeItem -> {
(holder as RecipeViewHolder).bind(item)
}

else ->
throw IllegalArgumentException("wrong type of holder")
}
}

fun changeRecipeItems(newChatList: List<RecipeListItem>) {
this.submitList(newChatList)
currentList
println()
}

enum class ViewType(val id: Int) {
CATEGORY(0),
RECIPE(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ru.otus.cookbook.cook_recycler_view

import androidx.recyclerview.widget.DiffUtil
import ru.otus.cookbook.data.RecipeListItem

class RecipeDiffutils : DiffUtil.ItemCallback<RecipeListItem>() {

override fun areItemsTheSame(oldItem: RecipeListItem, newItem: RecipeListItem): Boolean {
return oldItem== newItem
}

override fun areContentsTheSame(oldItem: RecipeListItem, newItem: RecipeListItem): Boolean {
return oldItem == newItem
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ru.otus.cookbook.cook_recycler_view

import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import ru.otus.cookbook.helpers.NavigateHelper

import ru.otus.cookbook.R
import ru.otus.cookbook.data.RecipeListItem

class RecipeViewHolder(private val recipeView: View) : RecyclerView.ViewHolder(recipeView) {

private val title: TextView by lazy { recipeView.findViewById(R.id.titleRecipe) }
private val description: TextView by lazy { recipeView.findViewById(R.id.titleDescription) }
private val imageRecipe: ImageView by lazy { recipeView.findViewById(R.id.imageRecipe) }


fun bind(recipeData: RecipeListItem.RecipeItem) {
recipeView.setOnClickListener { NavigateHelper.showMoreAboutRecipe(recipeData.id) }

title.text = recipeData.title
description.text = recipeData.description

Glide.with(recipeView.context)
.load(recipeData.imageUrl)
.into(imageRecipe)
}
}
24 changes: 12 additions & 12 deletions app/src/main/kotlin/ru/otus/cookbook/data/Recipe.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ val cookbook = listOf(
title = "Pasta Carbonara",
description = "Pasta Carbonara is a classic pasta dish from Rome with eggs, cheese and bacon.",
category = RecipeCategory("Pasta"),
imageUrl = "https://en.wikipedia.org/wiki/Carbonara#/media/File:Espaguetis_carbonara.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Espaguetis_carbonara.jpg/1920px-Espaguetis_carbonara.jpg",
steps = listOf(
"Cook the pasta in a large pot of boiling salted water until al dente.",
"Meanwhile, whisk the eggs and Parmesan together in a bowl.",
Expand All @@ -40,7 +40,7 @@ val cookbook = listOf(
title = "Fettuccine_Alfredo",
description = "Fettuccine Alfredo is a classic pasta dish from Rome with butter, cream and Parmesan.",
category = RecipeCategory("Pasta"),
imageUrl = "https://en.wikipedia.org/wiki/Fettuccine_Alfredo#/media/File:The_Only_Original_Alfredo_Sauce_with_Butter_and_Parmesano-Reggiano_Cheese.png",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/d/dc/The_Only_Original_Alfredo_Sauce_with_Butter_and_Parmesano-Reggiano_Cheese.png",
steps = listOf(
"Cook the fettuccine in a large pot of boiling salted water until al dente.",
"Meanwhile, melt the butter in a large pan over medium heat.",
Expand All @@ -57,7 +57,7 @@ val cookbook = listOf(
title = "Cod in breadcrumbs",
description = "Cod in breadcrumbs is a simple and delicious fish dish that is perfect for a quick and easy dinner.",
category = RecipeCategory("Fish"),
imageUrl = "https://en.wikipedia.org/wiki/Fish_finger#/media/File:Fishfinger_classic_fried_2.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Fishfinger_classic_fried_2.jpg/1920px-Fishfinger_classic_fried_2.jpg",
steps = listOf(
"Preheat the oven to 200C/180C Fan/Gas 6.",
"Place the cod fillets on a baking tray.",
Expand All @@ -72,7 +72,7 @@ val cookbook = listOf(
title = "Beef Stroganoff",
description = "Beef Stroganoff is a classic Russian dish made with beef, mushrooms and sour cream.",
category = RecipeCategory("Beef"),
imageUrl = "https://en.wikipedia.org/wiki/Beef_Stroganoff#/media/File:Moscow_(8351271825).jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Moscow_%288351271825%29.jpg/1920px-Moscow_%288351271825%29.jpg",
steps = listOf(
"Heat the oil in a large pan over medium heat.",
"Add the beef and cook until browned.",
Expand All @@ -89,7 +89,7 @@ val cookbook = listOf(
title = "Chicken Tikka Masala",
description = "Chicken Tikka Masala is a classic Indian dish made with marinated chicken cooked in a spicy tomato sauce.",
category = RecipeCategory("Chicken"),
imageUrl = "https://en.wikipedia.org/wiki/Chicken_tikka_masala#/media/File:Chicken_tikka_masala.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Chicken_tikka_masala.jpg/800px-Chicken_tikka_masala.jpg",
steps = listOf(
"Marinate the chicken in the yogurt, lemon juice, garlic, ginger, garam masala, turmeric, cumin, coriander, paprika, salt and pepper for at least 1 hour.",
"Heat the oil in a large pan over medium heat.",
Expand All @@ -106,7 +106,7 @@ val cookbook = listOf(
title = "Solyanka",
description = "Solyanka is a traditional Russian soup made with meat, pickles, olives and capers.",
category = RecipeCategory("Soup"),
imageUrl = "https://en.wikipedia.org/wiki/Solyanka#/media/File:Soljanka_food_05.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Soljanka_food_05.jpg/1280px-Soljanka_food_05.jpg",
steps = listOf(
"Heat the oil in a large pan over medium heat.",
"Add the onion, garlic, carrots and celery and cook until softened.",
Expand All @@ -122,7 +122,7 @@ val cookbook = listOf(
title = "Surströmming",
description = "Surströmming is a traditional Swedish dish made with fermented herring.",
category = RecipeCategory("Fish"),
imageUrl = "https://en.wikipedia.org/wiki/Surstr%C3%B6mming#/media/File:Surstr%C3%B6mming.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Surströmming.jpg/1280px-Surströmming.jpg",
steps = listOf(
"Open the can of surströmming outdoors, as the smell is very strong",
"Remove the herring from the can and rinse it under cold water",
Expand All @@ -135,7 +135,7 @@ val cookbook = listOf(
title = "Sichuang Hotpot",
description = "Sichuang Hotpot is a traditional Chinese dish made with spicy broth, meat, vegetables and noodles.",
category = RecipeCategory("Chinese"),
imageUrl = "https://en.wikipedia.org/wiki/Chongqing_hot_pot#/media/File:Chongqing_hotpot_2.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Chongqing_hotpot_2.jpg/1280px-Chongqing_hotpot_2.jpg",
steps = listOf(
"Prepare the broth by boiling water with Sichuang peppercorns, dried chilies, ginger, garlic, star anise, cinnamon and bay leaves",
"Add the meat, vegetables and noodles to the broth and cook until tender",
Expand All @@ -147,7 +147,7 @@ val cookbook = listOf(
title = "Tiramisu",
description = "Tiramisu is a classic Italian dessert made with coffee, mascarpone cheese, eggs, sugar and ladyfingers.",
category = RecipeCategory("Dessert"),
imageUrl = "https://en.wikipedia.org/wiki/Tiramisu#/media/File:Tiramisu_-_Raffaele_Diomede.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Tiramisu_-_Raffaele_Diomede.jpg/1280px-Tiramisu_-_Raffaele_Diomede.jpg",
steps = listOf(
"Brew the coffee and let it cool",
"Whisk the egg yolks and sugar together until pale and creamy",
Expand All @@ -165,7 +165,7 @@ val cookbook = listOf(
title = "Borscht",
description = "Borscht is a traditional Russian soup made with beets, cabbage, potatoes and beef.",
category = RecipeCategory("Soup"),
imageUrl = "https://en.wikipedia.org/wiki/Borscht#/media/File:Borscht_served.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Borscht_served.jpg/1920px-Borscht_served.jpg",
steps = listOf(
"Heat the oil in a large pan over medium heat.",
"Add the onion, garlic, carrots and celery and cook until softened.",
Expand All @@ -181,7 +181,7 @@ val cookbook = listOf(
title = "Peking Duck",
description = "Peking Duck is a traditional Chinese dish made with roasted duck, pancakes, hoisin sauce and cucumber.",
category = RecipeCategory("Chinese"),
imageUrl = "https://en.wikipedia.org/wiki/Peking_duck#/media/File:Peking_Duck,_2014_(02).jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/Peking_Duck%2C_2014_%2802%29.jpg/1280px-Peking_Duck%2C_2014_%2802%29.jpg",
steps = listOf(
"Prepare the duck by removing the giblets and excess fat",
"Rub the duck with a mixture of honey, soy sauce, five-spice powder and salt",
Expand All @@ -195,7 +195,7 @@ val cookbook = listOf(
title = "Sushi",
description = "Sushi is a traditional Japanese dish made with vinegared rice, fish, vegetables and seaweed.",
category = RecipeCategory("Japanese"),
imageUrl = "https://en.wikipedia.org/wiki/Sushi#/media/File:Sushi_platter.jpg",
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Sushi_platter.jpg/1024px-Sushi_platter.jpg",
steps = listOf(
"Cook the rice and season with rice vinegar, sugar and salt",
"Prepare the fish and vegetables by slicing them into thin strips",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ sealed class RecipeListItem : WithLayoutId {
data class CategoryItem(val category: RecipeCategory) : RecipeListItem(), WithLayoutId by CategoryItem {
companion object : WithLayoutId {
@get:LayoutRes
override val layoutId: Int = R.layout.vh_recipe_category
override val layoutId: Int = R.layout.vh_recipe_item
}

val name: String get() = category.name
Expand Down
39 changes: 39 additions & 0 deletions app/src/main/kotlin/ru/otus/cookbook/helpers/NavigateHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ru.otus.cookbook.helpers

import android.annotation.SuppressLint
import androidx.navigation.NavController
import ru.otus.cookbook.ui.CookbookFragmentDirections
import ru.otus.cookbook.ui.RecipeFragment
import ru.otus.cookbook.ui.RecipeFragmentDirections
import ru.otus.cookbook.R

object NavigateHelper {

@SuppressLint("StaticFieldLeak")
private var _navController: NavController? = null
private var _recipeFragment: RecipeFragment? = null

fun setNavController(navController: NavController) {
_navController = navController
}

fun showMoreAboutRecipe(id: Int) {
val action =
CookbookFragmentDirections.actionCookbookFragmentToRecipeFragment(recipeId = id)
_navController?.navigate(action)
}

fun showAlertDialogOnRecipeFragment(recipeName: String, recipeFragment: RecipeFragment) {
_recipeFragment = recipeFragment
val action =
RecipeFragmentDirections.actionRecipeFragmentToAlertDialogDialogFragment(recipeName)
_navController?.navigate(action)
}

fun onDelete() {
_recipeFragment?.onAlertDialogDelete()
_navController?.popBackStack(R.id.cookbookFragment, false)
_recipeFragment = null
}
}

32 changes: 32 additions & 0 deletions app/src/main/kotlin/ru/otus/cookbook/ui/AlertDialogFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ru.otus.cookbook.ui

import ru.otus.cookbook.R
import android.app.Dialog
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.navArgs
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import ru.otus.cookbook.helpers.NavigateHelper


class AlertDialogFragment : DialogFragment() {
private val args: AlertDialogFragmentArgs by navArgs()
private val recipeName: String get() = args.recipeName

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

val builder = activity?.let { MaterialAlertDialogBuilder(it) }

builder?.apply {
setTitle("Delete")
setMessage("Are you sure you want to delete $recipeName ?")
setNegativeButton("Cancel") { _, _ ->
return@setNegativeButton
}
setPositiveButton("OK") { _, _ ->
NavigateHelper.onDelete()
}
}
return builder?.create()!!
}
}
20 changes: 18 additions & 2 deletions app/src/main/kotlin/ru/otus/cookbook/ui/CookbookFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DividerItemDecoration
import kotlinx.coroutines.launch
import ru.otus.cookbook.R
import ru.otus.cookbook.cook_recycler_view.RecipeAdapter
import ru.otus.cookbook.helpers.NavigateHelper
import ru.otus.cookbook.data.RecipeListItem
import ru.otus.cookbook.databinding.FragmentCookbookBinding

class CookbookFragment : Fragment() {

private val binding = FragmentBindingDelegate<FragmentCookbookBinding>(this)
private val model: CookbookFragmentViewModel by viewModels { CookbookFragmentViewModel.Factory }
private val recipeAdapter by lazy { RecipeAdapter() }

override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -37,10 +44,19 @@ class CookbookFragment : Fragment() {
}

private fun setupRecyclerView() = binding.withBinding {
// Setup RecyclerView

val navController = findNavController()
NavigateHelper.setNavController(navController)

cardRecipesRcView.adapter = recipeAdapter

val divider = DividerItemDecoration(this@CookbookFragment.context,DividerItemDecoration.VERTICAL)
divider.setDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.divider_rv)!!)

cardRecipesRcView.addItemDecoration(divider)
}

private fun onRecipeListUpdated(recipeList: List<RecipeListItem>) {
// Handle recipe list
recipeAdapter.changeRecipeItems(recipeList)
}
}
Loading