├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── markdown-navigator-enh.xml ├── markdown-navigator.xml └── misc.xml ├── RecipeApp.zip ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── codingwithme │ │ └── recipeapp │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── codingwithme │ │ │ └── recipeapp │ │ │ ├── BaseActivity.kt │ │ │ ├── DetailActivity.kt │ │ │ ├── HomeActivity.kt │ │ │ ├── SplashActivity.kt │ │ │ ├── adapter │ │ │ ├── MainCategoryAdapter.kt │ │ │ └── SubCategoryAdapter.kt │ │ │ ├── dao │ │ │ └── RecipeDao.kt │ │ │ ├── database │ │ │ └── RecipeDatabase.kt │ │ │ ├── entities │ │ │ ├── Category.kt │ │ │ ├── CategoryItems.kt │ │ │ ├── Meal.kt │ │ │ ├── MealResponse.kt │ │ │ ├── MealsItems.kt │ │ │ ├── Recipes.kt │ │ │ └── converter │ │ │ │ ├── CategoryListConverter.kt │ │ │ │ └── MealListConverter.kt │ │ │ ├── interfaces │ │ │ └── GetDataService.kt │ │ │ └── retofitclient │ │ │ └── RetrofitClientInstance.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bg_splash.png │ │ ├── btn_bg.xml │ │ ├── btn_bg2.xml │ │ ├── btn_bg3.xml │ │ ├── cat_img.png │ │ ├── ic_back.xml │ │ ├── ic_baseline_access_time_24.xml │ │ ├── ic_fav_unfill.xml │ │ ├── ic_launcher_background.xml │ │ └── search_bg.xml │ │ ├── font │ │ ├── gilroy_bold.otf │ │ └── gilroy_light.otf │ │ ├── layout │ │ ├── activity_detail.xml │ │ ├── activity_home.xml │ │ ├── activity_splash.xml │ │ ├── item_rv_main_category.xml │ │ └── item_rv_sub_category.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── codingwithme │ └── recipeapp │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 122 | 123 | 125 | 126 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/markdown-navigator-enh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /RecipeApp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-with-me/RecipeApp/4ff5031c857c199dd1acdf4461cbc6c33dc9f133/RecipeApp.zip -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'kotlin-android-extensions' 5 | id 'kotlin-kapt' 6 | } 7 | 8 | android { 9 | compileSdkVersion 30 10 | buildToolsVersion "30.0.1" 11 | 12 | defaultConfig { 13 | applicationId "com.codingwithme.recipeapp" 14 | minSdkVersion 22 15 | targetSdkVersion 30 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | } 35 | } 36 | 37 | dependencies { 38 | 39 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 40 | implementation 'androidx.appcompat:appcompat:1.0.0' 41 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 42 | testImplementation 'junit:junit:4.+' 43 | implementation 'androidx.core:core-ktx:1.3.2' 44 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 45 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 46 | 47 | //dependencies 48 | //material design 49 | implementation 'com.google.android.material:material:1.2.1' 50 | 51 | //circle image view 52 | implementation 'de.hdodenhof:circleimageview:3.1.0' 53 | 54 | //scalable unit text size 55 | implementation 'com.intuit.ssp:ssp-android:1.0.6' 56 | 57 | //scalable unit size 58 | implementation 'com.intuit.sdp:sdp-android:1.0.6' 59 | 60 | //room database 61 | implementation 'androidx.room:room-runtime:2.2.5' 62 | kapt 'androidx.room:room-compiler:2.2.5' 63 | implementation 'androidx.room:room-ktx:2.2.1' 64 | implementation 'com.makeramen:roundedimageview:2.3.0' 65 | implementation "androidx.recyclerview:recyclerview:1.1.0" 66 | //crop image library 67 | 68 | implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' 69 | 70 | //easy permission 71 | 72 | implementation 'pub.devrel:easypermissions:3.0.0' 73 | 74 | //coroutines core 75 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1' 76 | 77 | //retrofit 78 | implementation 'com.squareup.retrofit2:retrofit:2.9.0' 79 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0' 80 | 81 | 82 | implementation 'com.github.bumptech.glide:glide:4.11.0' 83 | annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' 84 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/codingwithme/recipeapp/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.codingwithme.recipeapp", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp 2 | 3 | import android.app.job.JobInfo 4 | import android.content.Intent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import android.os.Bundle 7 | import kotlinx.coroutines.CoroutineScope 8 | import kotlinx.coroutines.Dispatchers 9 | import kotlinx.coroutines.Job 10 | import kotlin.coroutines.CoroutineContext 11 | 12 | open class BaseActivity : AppCompatActivity(),CoroutineScope { 13 | private lateinit var job: Job 14 | override val coroutineContext:CoroutineContext 15 | get() = job +Dispatchers.Main 16 | 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | job = Job() 21 | } 22 | 23 | override fun onDestroy() { 24 | super.onDestroy() 25 | job.cancel() 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/DetailActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp 2 | 3 | 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Bundle 7 | import android.view.View 8 | import android.widget.Toast 9 | import com.bumptech.glide.Glide 10 | import com.codingwithme.recipeapp.entities.MealResponse 11 | import com.codingwithme.recipeapp.interfaces.GetDataService 12 | import com.codingwithme.recipeapp.retofitclient.RetrofitClientInstance 13 | import kotlinx.android.synthetic.main.activity_detail.* 14 | import retrofit2.Call 15 | import retrofit2.Callback 16 | import retrofit2.Response 17 | 18 | 19 | class DetailActivity : BaseActivity() { 20 | 21 | var youtubeLink = "" 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_detail) 25 | 26 | var id = intent.getStringExtra("id") 27 | 28 | getSpecificItem(id!!) 29 | 30 | imgToolbarBtnBack.setOnClickListener { 31 | finish() 32 | } 33 | 34 | btnYoutube.setOnClickListener { 35 | val uri = Uri.parse(youtubeLink) 36 | val intent = Intent(Intent.ACTION_VIEW, uri) 37 | startActivity(intent) 38 | } 39 | 40 | } 41 | 42 | fun getSpecificItem(id:String) { 43 | val service = RetrofitClientInstance.retrofitInstance!!.create(GetDataService::class.java) 44 | val call = service.getSpecificItem(id) 45 | call.enqueue(object : Callback { 46 | override fun onFailure(call: Call, t: Throwable) { 47 | 48 | Toast.makeText(this@DetailActivity, "Something went wrong", Toast.LENGTH_SHORT) 49 | .show() 50 | } 51 | 52 | override fun onResponse( 53 | call: Call, 54 | response: Response 55 | ) { 56 | 57 | Glide.with(this@DetailActivity).load(response.body()!!.mealsEntity[0].strmealthumb).into(imgItem) 58 | 59 | tvCategory.text = response.body()!!.mealsEntity[0].strmeal 60 | 61 | var ingredient = "${response.body()!!.mealsEntity[0].stringredient1} ${response.body()!!.mealsEntity[0].strmeasure1}\n" + 62 | "${response.body()!!.mealsEntity[0].stringredient2} ${response.body()!!.mealsEntity[0].strmeasure2}\n" + 63 | "${response.body()!!.mealsEntity[0].stringredient3} ${response.body()!!.mealsEntity[0].strmeasure3}\n" + 64 | "${response.body()!!.mealsEntity[0].stringredient4} ${response.body()!!.mealsEntity[0].strmeasure4}\n" + 65 | "${response.body()!!.mealsEntity[0].stringredient5} ${response.body()!!.mealsEntity[0].strmeasure5}\n" + 66 | "${response.body()!!.mealsEntity[0].stringredient6} ${response.body()!!.mealsEntity[0].strmeasure6}\n" + 67 | "${response.body()!!.mealsEntity[0].stringredient7} ${response.body()!!.mealsEntity[0].strmeasure7}\n" + 68 | "${response.body()!!.mealsEntity[0].stringredient8} ${response.body()!!.mealsEntity[0].strmeasure8}\n" + 69 | "${response.body()!!.mealsEntity[0].stringredient9} ${response.body()!!.mealsEntity[0].strmeasure9}\n" + 70 | "${response.body()!!.mealsEntity[0].stringredient10} ${response.body()!!.mealsEntity[0].strmeasure10}\n" + 71 | "${response.body()!!.mealsEntity[0].stringredient11} ${response.body()!!.mealsEntity[0].strmeasure11}\n" + 72 | "${response.body()!!.mealsEntity[0].stringredient12} ${response.body()!!.mealsEntity[0].strmeasure12}\n" + 73 | "${response.body()!!.mealsEntity[0].stringredient13} ${response.body()!!.mealsEntity[0].strmeasure13}\n" + 74 | "${response.body()!!.mealsEntity[0].stringredient14} ${response.body()!!.mealsEntity[0].strmeasure14}\n" + 75 | "${response.body()!!.mealsEntity[0].stringredient15} ${response.body()!!.mealsEntity[0].strmeasure15}\n" + 76 | "${response.body()!!.mealsEntity[0].stringredient16} ${response.body()!!.mealsEntity[0].strmeasure16}\n" + 77 | "${response.body()!!.mealsEntity[0].stringredient17} ${response.body()!!.mealsEntity[0].strmeasure17}\n" + 78 | "${response.body()!!.mealsEntity[0].stringredient18} ${response.body()!!.mealsEntity[0].strmeasure18}\n" + 79 | "${response.body()!!.mealsEntity[0].stringredient19} ${response.body()!!.mealsEntity[0].strmeasure19}\n" + 80 | "${response.body()!!.mealsEntity[0].stringredient20} ${response.body()!!.mealsEntity[0].strmeasure20}\n" 81 | 82 | tvIngredients.text = ingredient 83 | tvInstructions.text = response.body()!!.mealsEntity[0].strinstructions 84 | 85 | if (response.body()!!.mealsEntity[0].strsource != null){ 86 | youtubeLink = response.body()!!.mealsEntity[0].strsource 87 | }else{ 88 | btnYoutube.visibility = View.GONE 89 | } 90 | } 91 | 92 | }) 93 | } 94 | 95 | 96 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/HomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import androidx.recyclerview.widget.LinearLayoutManager 7 | import com.codingwithme.recipeapp.adapter.MainCategoryAdapter 8 | import com.codingwithme.recipeapp.adapter.SubCategoryAdapter 9 | import com.codingwithme.recipeapp.database.RecipeDatabase 10 | import com.codingwithme.recipeapp.entities.Category 11 | import com.codingwithme.recipeapp.entities.CategoryItems 12 | import com.codingwithme.recipeapp.entities.MealsItems 13 | import com.codingwithme.recipeapp.entities.Recipes 14 | import kotlinx.android.synthetic.main.activity_home.* 15 | import kotlinx.coroutines.launch 16 | 17 | class HomeActivity : BaseActivity() { 18 | var arrMainCategory = ArrayList() 19 | var arrSubCategory = ArrayList() 20 | 21 | var mainCategoryAdapter = MainCategoryAdapter() 22 | var subCategoryAdapter = SubCategoryAdapter() 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.activity_home) 27 | 28 | 29 | getDataFromDb() 30 | 31 | mainCategoryAdapter.setClickListener(onCLicked) 32 | subCategoryAdapter.setClickListener(onCLickedSubItem) 33 | 34 | 35 | 36 | 37 | } 38 | 39 | private val onCLicked = object : MainCategoryAdapter.OnItemClickListener{ 40 | override fun onClicked(categoryName: String) { 41 | getMealDataFromDb(categoryName) 42 | } 43 | } 44 | 45 | private val onCLickedSubItem = object : SubCategoryAdapter.OnItemClickListener{ 46 | override fun onClicked(id: String) { 47 | var intent = Intent(this@HomeActivity,DetailActivity::class.java) 48 | intent.putExtra("id",id) 49 | startActivity(intent) 50 | } 51 | } 52 | 53 | private fun getDataFromDb(){ 54 | launch { 55 | this.let { 56 | var cat = RecipeDatabase.getDatabase(this@HomeActivity).recipeDao().getAllCategory() 57 | arrMainCategory = cat as ArrayList 58 | arrMainCategory.reverse() 59 | 60 | getMealDataFromDb(arrMainCategory[0].strcategory) 61 | mainCategoryAdapter.setData(arrMainCategory) 62 | rv_main_category.layoutManager = LinearLayoutManager(this@HomeActivity,LinearLayoutManager.HORIZONTAL,false) 63 | rv_main_category.adapter = mainCategoryAdapter 64 | } 65 | 66 | 67 | } 68 | } 69 | 70 | private fun getMealDataFromDb(categoryName:String){ 71 | tvCategory.text = "$categoryName Category" 72 | launch { 73 | this.let { 74 | var cat = RecipeDatabase.getDatabase(this@HomeActivity).recipeDao().getSpecificMealList(categoryName) 75 | arrSubCategory = cat as ArrayList 76 | subCategoryAdapter.setData(arrSubCategory) 77 | rv_sub_category.layoutManager = LinearLayoutManager(this@HomeActivity,LinearLayoutManager.HORIZONTAL,false) 78 | rv_sub_category.adapter = subCategoryAdapter 79 | } 80 | 81 | 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.View 7 | import android.widget.Toast 8 | import com.codingwithme.recipeapp.database.RecipeDatabase 9 | import com.codingwithme.recipeapp.entities.Category 10 | import com.codingwithme.recipeapp.entities.CategoryItems 11 | import com.codingwithme.recipeapp.entities.Meal 12 | import com.codingwithme.recipeapp.entities.MealsItems 13 | import com.codingwithme.recipeapp.interfaces.GetDataService 14 | import com.codingwithme.recipeapp.retofitclient.RetrofitClientInstance 15 | import kotlinx.android.synthetic.main.activity_splash.* 16 | import kotlinx.coroutines.CoroutineScope 17 | import kotlinx.coroutines.launch 18 | import pub.devrel.easypermissions.AppSettingsDialog 19 | import pub.devrel.easypermissions.EasyPermissions 20 | import retrofit2.Call 21 | import retrofit2.Callback 22 | import retrofit2.Response 23 | import java.util.jar.Manifest 24 | 25 | class SplashActivity : BaseActivity(), EasyPermissions.RationaleCallbacks, 26 | EasyPermissions.PermissionCallbacks { 27 | private var READ_STORAGE_PERM = 123 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | setContentView(R.layout.activity_splash) 31 | 32 | readStorageTask() 33 | 34 | btnGetStarted.setOnClickListener { 35 | var intent = Intent(this@SplashActivity, HomeActivity::class.java) 36 | startActivity(intent) 37 | finish() 38 | } 39 | } 40 | 41 | 42 | fun getCategories() { 43 | val service = RetrofitClientInstance.retrofitInstance!!.create(GetDataService::class.java) 44 | val call = service.getCategoryList() 45 | call.enqueue(object : Callback { 46 | override fun onFailure(call: Call, t: Throwable) { 47 | 48 | Toast.makeText(this@SplashActivity, "Something went wrong", Toast.LENGTH_SHORT) 49 | .show() 50 | } 51 | 52 | override fun onResponse( 53 | call: Call, 54 | response: Response 55 | ) { 56 | 57 | for (arr in response.body()!!.categorieitems!!) { 58 | getMeal(arr.strcategory) 59 | } 60 | insertDataIntoRoomDb(response.body()) 61 | } 62 | 63 | }) 64 | } 65 | 66 | 67 | fun getMeal(categoryName: String) { 68 | val service = RetrofitClientInstance.retrofitInstance!!.create(GetDataService::class.java) 69 | val call = service.getMealList(categoryName) 70 | call.enqueue(object : Callback { 71 | override fun onFailure(call: Call, t: Throwable) { 72 | 73 | loader.visibility = View.INVISIBLE 74 | Toast.makeText(this@SplashActivity, "Something went wrong", Toast.LENGTH_SHORT) 75 | .show() 76 | } 77 | 78 | override fun onResponse( 79 | call: Call, 80 | response: Response 81 | ) { 82 | 83 | insertMealDataIntoRoomDb(categoryName, response.body()) 84 | } 85 | 86 | }) 87 | } 88 | 89 | fun insertDataIntoRoomDb(category: Category?) { 90 | 91 | launch { 92 | this.let { 93 | 94 | for (arr in category!!.categorieitems!!) { 95 | RecipeDatabase.getDatabase(this@SplashActivity) 96 | .recipeDao().insertCategory(arr) 97 | } 98 | } 99 | } 100 | 101 | 102 | } 103 | 104 | fun insertMealDataIntoRoomDb(categoryName: String, meal: Meal?) { 105 | 106 | launch { 107 | this.let { 108 | 109 | 110 | for (arr in meal!!.mealsItem!!) { 111 | var mealItemModel = MealsItems( 112 | arr.id, 113 | arr.idMeal, 114 | categoryName, 115 | arr.strMeal, 116 | arr.strMealThumb 117 | ) 118 | RecipeDatabase.getDatabase(this@SplashActivity) 119 | .recipeDao().insertMeal(mealItemModel) 120 | Log.d("mealData", arr.toString()) 121 | } 122 | 123 | btnGetStarted.visibility = View.VISIBLE 124 | } 125 | } 126 | 127 | 128 | } 129 | 130 | fun clearDataBase() { 131 | launch { 132 | this.let { 133 | RecipeDatabase.getDatabase(this@SplashActivity).recipeDao().clearDb() 134 | } 135 | } 136 | } 137 | 138 | private fun hasReadStoragePermission(): Boolean { 139 | return EasyPermissions.hasPermissions( 140 | this, 141 | android.Manifest.permission.READ_EXTERNAL_STORAGE 142 | ) 143 | } 144 | 145 | private fun readStorageTask() { 146 | if (hasReadStoragePermission()) { 147 | clearDataBase() 148 | getCategories() 149 | } else { 150 | EasyPermissions.requestPermissions( 151 | this, 152 | "This app needs access to your storage,", 153 | READ_STORAGE_PERM, 154 | android.Manifest.permission.READ_EXTERNAL_STORAGE 155 | ) 156 | } 157 | } 158 | 159 | override fun onRequestPermissionsResult( 160 | requestCode: Int, 161 | permissions: Array, 162 | grantResults: IntArray 163 | ) { 164 | super.onRequestPermissionsResult(requestCode, permissions, grantResults) 165 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) 166 | } 167 | 168 | override fun onRationaleDenied(requestCode: Int) { 169 | 170 | } 171 | 172 | override fun onRationaleAccepted(requestCode: Int) { 173 | 174 | } 175 | 176 | override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { 177 | if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { 178 | AppSettingsDialog.Builder(this).build().show() 179 | } 180 | } 181 | 182 | override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { 183 | 184 | } 185 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/adapter/MainCategoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.adapter 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.codingwithme.recipeapp.R 10 | import com.codingwithme.recipeapp.entities.CategoryItems 11 | import com.codingwithme.recipeapp.entities.Recipes 12 | import kotlinx.android.synthetic.main.item_rv_main_category.view.* 13 | 14 | class MainCategoryAdapter: RecyclerView.Adapter() { 15 | 16 | var listener: OnItemClickListener? = null 17 | var ctx: Context? = null 18 | var arrMainCategory = ArrayList() 19 | class RecipeViewHolder(view: View): RecyclerView.ViewHolder(view){ 20 | 21 | } 22 | 23 | fun setData(arrData : List){ 24 | arrMainCategory = arrData as ArrayList 25 | } 26 | 27 | fun setClickListener(listener1: OnItemClickListener){ 28 | listener = listener1 29 | } 30 | 31 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder { 32 | ctx = parent.context 33 | return RecipeViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_rv_main_category,parent,false)) 34 | } 35 | 36 | override fun getItemCount(): Int { 37 | return arrMainCategory.size 38 | } 39 | 40 | override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) { 41 | 42 | holder.itemView.tv_dish_name.text = arrMainCategory[position].strcategory 43 | Glide.with(ctx!!).load(arrMainCategory[position].strcategorythumb).into(holder.itemView.img_dish) 44 | holder.itemView.rootView.setOnClickListener { 45 | listener!!.onClicked(arrMainCategory[position].strcategory) 46 | } 47 | } 48 | 49 | interface OnItemClickListener{ 50 | fun onClicked(categoryName:String) 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/adapter/SubCategoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.adapter 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.codingwithme.recipeapp.R 10 | import com.codingwithme.recipeapp.entities.MealsItems 11 | import com.codingwithme.recipeapp.entities.Recipes 12 | import kotlinx.android.synthetic.main.item_rv_main_category.view.* 13 | 14 | class SubCategoryAdapter: RecyclerView.Adapter() { 15 | 16 | var listener: SubCategoryAdapter.OnItemClickListener? = null 17 | var ctx :Context? = null 18 | var arrSubCategory = ArrayList() 19 | class RecipeViewHolder(view: View): RecyclerView.ViewHolder(view){ 20 | 21 | } 22 | 23 | fun setData(arrData : List){ 24 | arrSubCategory = arrData as ArrayList 25 | } 26 | 27 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder { 28 | ctx = parent.context 29 | return RecipeViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_rv_sub_category,parent,false)) 30 | } 31 | 32 | override fun getItemCount(): Int { 33 | return arrSubCategory.size 34 | } 35 | 36 | fun setClickListener(listener1: SubCategoryAdapter.OnItemClickListener){ 37 | listener = listener1 38 | } 39 | 40 | override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) { 41 | 42 | holder.itemView.tv_dish_name.text = arrSubCategory[position].strMeal 43 | 44 | Glide.with(ctx!!).load(arrSubCategory[position].strMealThumb).into(holder.itemView.img_dish) 45 | 46 | holder.itemView.rootView.setOnClickListener { 47 | listener!!.onClicked(arrSubCategory[position].idMeal) 48 | } 49 | } 50 | 51 | interface OnItemClickListener{ 52 | fun onClicked(id:String) 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/dao/RecipeDao.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.OnConflictStrategy 6 | import androidx.room.Query 7 | import com.codingwithme.recipeapp.entities.Category 8 | import com.codingwithme.recipeapp.entities.CategoryItems 9 | import com.codingwithme.recipeapp.entities.MealsItems 10 | 11 | @Dao 12 | interface RecipeDao { 13 | 14 | @Query("SELECT * FROM categoryitems ORDER BY id DESC") 15 | suspend fun getAllCategory() : List 16 | 17 | @Insert(onConflict = OnConflictStrategy.REPLACE) 18 | suspend fun insertCategory(categoryItems: CategoryItems?) 19 | 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | suspend fun insertMeal(mealsItems: MealsItems?) 22 | 23 | @Query("DELETE FROM categoryitems") 24 | suspend fun clearDb() 25 | 26 | @Query("SELECT * FROM MealItems WHERE categoryName = :categoryName ORDER BY id DESC") 27 | suspend fun getSpecificMealList(categoryName:String) : List 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/database/RecipeDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.database 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import androidx.room.TypeConverters 8 | import com.codingwithme.recipeapp.dao.RecipeDao 9 | import com.codingwithme.recipeapp.entities.* 10 | import com.codingwithme.recipeapp.entities.converter.CategoryListConverter 11 | import com.codingwithme.recipeapp.entities.converter.MealListConverter 12 | 13 | @Database(entities = [Recipes::class,CategoryItems::class,Category::class,Meal::class,MealsItems::class],version = 1,exportSchema = false) 14 | @TypeConverters(CategoryListConverter::class,MealListConverter::class) 15 | abstract class RecipeDatabase: RoomDatabase() { 16 | 17 | companion object{ 18 | 19 | var recipesDatabase:RecipeDatabase? = null 20 | 21 | @Synchronized 22 | fun getDatabase(context: Context): RecipeDatabase{ 23 | if (recipesDatabase == null){ 24 | recipesDatabase = Room.databaseBuilder( 25 | context, 26 | RecipeDatabase::class.java, 27 | "recipe.db" 28 | ).build() 29 | } 30 | return recipesDatabase!! 31 | } 32 | } 33 | 34 | abstract fun recipeDao():RecipeDao 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/Category.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import androidx.room.* 4 | import com.codingwithme.recipeapp.entities.converter.CategoryListConverter 5 | import com.google.gson.annotations.Expose 6 | import com.google.gson.annotations.SerializedName 7 | 8 | @Entity(tableName = "Category") 9 | data class Category( 10 | @PrimaryKey(autoGenerate = true) 11 | var id:Int, 12 | 13 | @ColumnInfo(name = "categoryItems") 14 | @Expose 15 | @SerializedName("categories") 16 | @TypeConverters(CategoryListConverter::class) 17 | var categorieitems: List? = null 18 | ) 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/CategoryItems.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import com.google.gson.annotations.Expose 7 | import com.google.gson.annotations.SerializedName 8 | @Entity(tableName = "CategoryItems") 9 | data class CategoryItems( 10 | @PrimaryKey(autoGenerate = true) 11 | var id:Int, 12 | 13 | @ColumnInfo(name = "idcategory") 14 | @Expose 15 | @SerializedName("idCategory") 16 | val idcategory: String, 17 | 18 | @ColumnInfo(name = "strcategory") 19 | @Expose 20 | @SerializedName("strCategory") 21 | val strcategory: String, 22 | 23 | @ColumnInfo(name = "strcategorythumb") 24 | @Expose 25 | @SerializedName("strCategoryThumb") 26 | val strcategorythumb: String, 27 | 28 | @ColumnInfo(name = "strcategorydescription") 29 | @Expose 30 | @SerializedName("strCategoryDescription") 31 | val strcategorydescription: String 32 | ) 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/Meal.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import androidx.room.TypeConverters 7 | import com.codingwithme.recipeapp.entities.converter.MealListConverter 8 | import com.google.gson.annotations.Expose 9 | import com.google.gson.annotations.SerializedName 10 | 11 | @Entity(tableName = "Meal") 12 | class Meal( 13 | 14 | @PrimaryKey(autoGenerate = true) 15 | var id:Int, 16 | 17 | @ColumnInfo(name = "meals") 18 | @Expose 19 | @SerializedName("meals") 20 | @TypeConverters(MealListConverter::class) 21 | var mealsItem: List? = null 22 | 23 | ) 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/MealResponse.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class MealResponse( 7 | @Expose 8 | @SerializedName("meals") 9 | var mealsEntity: List 10 | ) 11 | 12 | data class MealsEntity( 13 | @Expose 14 | @SerializedName("idMeal") 15 | val idmeal: String, 16 | @Expose 17 | @SerializedName("strMeal") 18 | val strmeal: String, 19 | @Expose 20 | @SerializedName("strCategory") 21 | val strcategory: String, 22 | @Expose 23 | @SerializedName("strArea") 24 | val strarea: String, 25 | @Expose 26 | @SerializedName("strInstructions") 27 | val strinstructions: String, 28 | @Expose 29 | @SerializedName("strMealThumb") 30 | val strmealthumb: String, 31 | @Expose 32 | @SerializedName("strTags") 33 | val strtags: String, 34 | @Expose 35 | @SerializedName("strYoutube") 36 | val stryoutube: String, 37 | @Expose 38 | @SerializedName("strIngredient1") 39 | val stringredient1: String, 40 | @Expose 41 | @SerializedName("strIngredient2") 42 | val stringredient2: String, 43 | @Expose 44 | @SerializedName("strIngredient3") 45 | val stringredient3: String, 46 | @Expose 47 | @SerializedName("strIngredient4") 48 | val stringredient4: String, 49 | @Expose 50 | @SerializedName("strIngredient5") 51 | val stringredient5: String, 52 | @Expose 53 | @SerializedName("strIngredient6") 54 | val stringredient6: String, 55 | @Expose 56 | @SerializedName("strIngredient7") 57 | val stringredient7: String, 58 | @Expose 59 | @SerializedName("strIngredient8") 60 | val stringredient8: String, 61 | @Expose 62 | @SerializedName("strIngredient9") 63 | val stringredient9: String, 64 | @Expose 65 | @SerializedName("strIngredient10") 66 | val stringredient10: String, 67 | @Expose 68 | @SerializedName("strIngredient11") 69 | val stringredient11: String, 70 | @Expose 71 | @SerializedName("strIngredient12") 72 | val stringredient12: String, 73 | @Expose 74 | @SerializedName("strIngredient13") 75 | val stringredient13: String, 76 | @Expose 77 | @SerializedName("strIngredient14") 78 | val stringredient14: String, 79 | @Expose 80 | @SerializedName("strIngredient15") 81 | val stringredient15: String, 82 | @Expose 83 | @SerializedName("strIngredient16") 84 | val stringredient16: String, 85 | @Expose 86 | @SerializedName("strIngredient17") 87 | val stringredient17: String, 88 | @Expose 89 | @SerializedName("strIngredient18") 90 | val stringredient18: String, 91 | @Expose 92 | @SerializedName("strIngredient19") 93 | val stringredient19: String, 94 | @Expose 95 | @SerializedName("strIngredient20") 96 | val stringredient20: String, 97 | @Expose 98 | @SerializedName("strMeasure1") 99 | val strmeasure1: String, 100 | @Expose 101 | @SerializedName("strMeasure2") 102 | val strmeasure2: String, 103 | @Expose 104 | @SerializedName("strMeasure3") 105 | val strmeasure3: String, 106 | @Expose 107 | @SerializedName("strMeasure4") 108 | val strmeasure4: String, 109 | @Expose 110 | @SerializedName("strMeasure5") 111 | val strmeasure5: String, 112 | @Expose 113 | @SerializedName("strMeasure6") 114 | val strmeasure6: String, 115 | @Expose 116 | @SerializedName("strMeasure7") 117 | val strmeasure7: String, 118 | @Expose 119 | @SerializedName("strMeasure8") 120 | val strmeasure8: String, 121 | @Expose 122 | @SerializedName("strMeasure9") 123 | val strmeasure9: String, 124 | @Expose 125 | @SerializedName("strMeasure10") 126 | val strmeasure10: String, 127 | @Expose 128 | @SerializedName("strMeasure11") 129 | val strmeasure11: String, 130 | @Expose 131 | @SerializedName("strMeasure12") 132 | val strmeasure12: String, 133 | @Expose 134 | @SerializedName("strMeasure13") 135 | val strmeasure13: String, 136 | @Expose 137 | @SerializedName("strMeasure14") 138 | val strmeasure14: String, 139 | @Expose 140 | @SerializedName("strMeasure15") 141 | val strmeasure15: String, 142 | @Expose 143 | @SerializedName("strMeasure16") 144 | val strmeasure16: String, 145 | @Expose 146 | @SerializedName("strMeasure17") 147 | val strmeasure17: String, 148 | @Expose 149 | @SerializedName("strMeasure18") 150 | val strmeasure18: String, 151 | @Expose 152 | @SerializedName("strMeasure19") 153 | val strmeasure19: String, 154 | @Expose 155 | @SerializedName("strMeasure20") 156 | val strmeasure20: String, 157 | @Expose 158 | @SerializedName("strSource") 159 | val strsource: String 160 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/MealsItems.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import com.google.gson.annotations.Expose 7 | import com.google.gson.annotations.SerializedName 8 | @Entity(tableName = "MealItems") 9 | data class MealsItems( 10 | @PrimaryKey(autoGenerate = true) 11 | var id:Int, 12 | 13 | @ColumnInfo(name = "idMeal") 14 | @Expose 15 | @SerializedName("idMeal") 16 | val idMeal: String, 17 | 18 | @ColumnInfo(name = "categoryName") 19 | val categoryName: String, 20 | 21 | @ColumnInfo(name = "strmeal") 22 | @Expose 23 | @SerializedName("strMeal") 24 | val strMeal: String, 25 | 26 | @ColumnInfo(name = "strmealthumb") 27 | @Expose 28 | @SerializedName("strMealThumb") 29 | val strMealThumb: String 30 | ) 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/Recipes.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import java.io.Serializable 7 | 8 | @Entity(tableName = "Recipes") 9 | data class Recipes( 10 | @PrimaryKey(autoGenerate = true) 11 | var id:Int, 12 | 13 | @ColumnInfo(name = "dishName") 14 | var dishName:String 15 | ) : Serializable -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/converter/CategoryListConverter.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities.converter 2 | 3 | import androidx.room.TypeConverter 4 | import androidx.room.TypeConverters 5 | import com.codingwithme.recipeapp.entities.Category 6 | import com.codingwithme.recipeapp.entities.CategoryItems 7 | import com.google.gson.Gson 8 | import com.google.gson.reflect.TypeToken 9 | 10 | class CategoryListConverter { 11 | @TypeConverter 12 | fun fromCategoryList(category: List):String?{ 13 | if (category == null){ 14 | return (null) 15 | }else{ 16 | val gson = Gson() 17 | val type = object : TypeToken(){ 18 | 19 | }.type 20 | return gson.toJson(category,type) 21 | } 22 | } 23 | 24 | @TypeConverter 25 | fun toCategoryList ( categoryString: String):List?{ 26 | if (categoryString == null){ 27 | return (null) 28 | }else{ 29 | val gson = Gson() 30 | val type = object :TypeToken(){ 31 | 32 | }.type 33 | return gson.fromJson(categoryString,type) 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/entities/converter/MealListConverter.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.entities.converter 2 | 3 | import androidx.room.TypeConverter 4 | import androidx.room.TypeConverters 5 | import com.codingwithme.recipeapp.entities.Category 6 | import com.codingwithme.recipeapp.entities.CategoryItems 7 | import com.codingwithme.recipeapp.entities.MealsItems 8 | import com.google.gson.Gson 9 | import com.google.gson.reflect.TypeToken 10 | 11 | class MealListConverter { 12 | @TypeConverter 13 | fun fromCategoryList(category: List):String?{ 14 | if (category == null){ 15 | return (null) 16 | }else{ 17 | val gson = Gson() 18 | val type = object : TypeToken(){ 19 | 20 | }.type 21 | return gson.toJson(category,type) 22 | } 23 | } 24 | 25 | @TypeConverter 26 | fun toCategoryList ( categoryString: String):List?{ 27 | if (categoryString == null){ 28 | return (null) 29 | }else{ 30 | val gson = Gson() 31 | val type = object :TypeToken(){ 32 | 33 | }.type 34 | return gson.fromJson(categoryString,type) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/interfaces/GetDataService.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.interfaces 2 | 3 | import com.codingwithme.recipeapp.entities.Category 4 | import com.codingwithme.recipeapp.entities.CategoryItems 5 | import com.codingwithme.recipeapp.entities.Meal 6 | import com.codingwithme.recipeapp.entities.MealResponse 7 | import retrofit2.Call 8 | import retrofit2.http.GET 9 | import retrofit2.http.Query 10 | 11 | interface GetDataService { 12 | @GET("categories.php") 13 | fun getCategoryList(): Call 14 | 15 | @GET("filter.php") 16 | fun getMealList(@Query("c") category: String): Call 17 | 18 | @GET("lookup.php") 19 | fun getSpecificItem(@Query("i") id: String): Call 20 | 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingwithme/recipeapp/retofitclient/RetrofitClientInstance.kt: -------------------------------------------------------------------------------- 1 | package com.codingwithme.recipeapp.retofitclient 2 | 3 | import retrofit2.Retrofit 4 | import retrofit2.converter.gson.GsonConverterFactory 5 | 6 | 7 | class RetrofitClientInstance { 8 | companion object{ 9 | val BASE_URL = "https://www.themealdb.com/api/json/v1/1/" 10 | private var retrofit: Retrofit? = null 11 | val retrofitInstance: Retrofit? 12 | get() { 13 | if (retrofit == null) { 14 | retrofit = Retrofit.Builder() 15 | .baseUrl(BASE_URL) 16 | .addConverterFactory(GsonConverterFactory.create()) 17 | .build() 18 | } 19 | return retrofit 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-with-me/RecipeApp/4ff5031c857c199dd1acdf4461cbc6c33dc9f133/app/src/main/res/drawable/bg_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_bg2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_bg3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cat_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-with-me/RecipeApp/4ff5031c857c199dd1acdf4461cbc6c33dc9f133/app/src/main/res/drawable/cat_img.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_access_time_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fav_unfill.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/font/gilroy_bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-with-me/RecipeApp/4ff5031c857c199dd1acdf4461cbc6c33dc9f133/app/src/main/res/font/gilroy_bold.otf -------------------------------------------------------------------------------- /app/src/main/res/font/gilroy_light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-with-me/RecipeApp/4ff5031c857c199dd1acdf4461cbc6c33dc9f133/app/src/main/res/font/gilroy_light.otf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 39 | 40 | 46 | 47 | 59 | 60 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 87 | 94 | 100 | 101 | 111 | 112 | 117 | 118 | 123 | 124 | 128 | 129 | 130 | 144 | 145 | 146 | 153 | 154 | 158 | 159 | 160 | 174 | 175 | 176 | 181 | 182 | 186 | 187 | 188 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 218 | 219 | 225 | 229 | 230 | 241 | 242 | 243 | 244 | 245 | 253 | 254 | 261 | 265 | 266 | 277 | 278 | 279 | 280 | 281 | 282 |