Skip to content

Commit

Permalink
Merge pull request #40 from mohand3del/feature/home
Browse files Browse the repository at this point in the history
Overwrite the recommended meals fetching mechanic with network checks and fixed dark mode
  • Loading branch information
mohand3del authored Sep 22, 2024
2 parents 22196d9 + f631511 commit 0ab89e1
Show file tree
Hide file tree
Showing 35 changed files with 738 additions and 677 deletions.
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface UserRepository {

suspend fun updateFavourites(favourites: List<String>)

suspend fun updateSubscriptionState()
suspend fun updateSubscriptionState(isSubscribed: Boolean)

suspend fun checkSubscriptionState(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class UserRepositoryImpl(private val userDataSource: LocalDataSource) : UserRepo
userDataSource.updateUserFavourites(favourites)
}

override suspend fun updateSubscriptionState() {
userDataSource.updateSubscriptionState()
override suspend fun updateSubscriptionState(isSubscribed: Boolean) {
userDataSource.updateSubscriptionState(isSubscribed)
}

override suspend fun checkSubscriptionState(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface LocalDataSource {

suspend fun updateUserFavourites(favourites: List<String>)

suspend fun updateSubscriptionState()
suspend fun updateSubscriptionState(isSubscribed: Boolean)

suspend fun checkSubscriptionState(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class LocalDataSourceImpl(private val userDao: UserDao) : LocalDataSource {
userDao.updateLoggedInUserFavourites(favourites)
}

override suspend fun updateSubscriptionState() {
userDao.updateSubscriptionState()
override suspend fun updateSubscriptionState(isSubscribed: Boolean) {
userDao.updateSubscriptionState(isSubscribed)
}

override suspend fun checkSubscriptionState(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ interface UserDao {
@Query("UPDATE user SET favourites = :favourites WHERE isLoggedIn = 1")
suspend fun updateLoggedInUserFavourites(favourites: List<String>)

@Query("UPDATE user SET isSubscribed = 1 WHERE isLoggedIn = 1")
suspend fun updateSubscriptionState()
@Query("UPDATE user SET isSubscribed = :subscribed WHERE isLoggedIn = 1")
suspend fun updateSubscriptionState(subscribed: Boolean)

@Query("SELECT isSubscribed FROM user WHERE isLoggedIn = 1")
suspend fun checkSubscriptionState(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.example.recipeappiti.core.model.remote.Response
import com.google.android.material.dialog.MaterialAlertDialogBuilder

object CreateMaterialAlertDialogBuilder {

fun createMaterialAlertDialogBuilderOkCancel(
context: Context,
title: String,
Expand All @@ -15,7 +14,6 @@ object CreateMaterialAlertDialogBuilder {
negativeBtnMsg: String,
positiveBtnFun: () -> Unit
) {

MaterialAlertDialogBuilder(context)
.setTitle(title)
.setMessage(message)
Expand All @@ -31,7 +29,6 @@ object CreateMaterialAlertDialogBuilder {
}
.setCancelable(false)
.show()

}

fun createMaterialAlertDialogBuilderOk(
Expand All @@ -41,7 +38,6 @@ object CreateMaterialAlertDialogBuilder {
positiveBtnMsg: String,
positiveBtnFun: () -> Unit
) {

MaterialAlertDialogBuilder(context)
.setTitle(title)
.setMessage(message)
Expand All @@ -53,21 +49,19 @@ object CreateMaterialAlertDialogBuilder {
}
.setCancelable(false)
.show()

}

fun createFailureResponse(response: Response.Failure, context: Context) {
fun createFailureResponse(response: Response.Failure, context: Context, action: (() -> Unit)? = null) {
when (val failureReason = response.reason) {
is FailureReason.NoInternet -> {

createMaterialAlertDialogBuilderOkCancel(
context,
title = "No Internet Connection",
message = "Please check your internet connection and try again.",
positiveBtnMsg = "Try again",
negativeBtnMsg = "Cancel"
) {
//TODO Optionally, define any action to take after the dialog is dismissed
action?.invoke()
}
}

Expand All @@ -77,12 +71,11 @@ object CreateMaterialAlertDialogBuilder {
context,
title = "Unknown Error",
message = "An unknown error occurred: $errorMessage",
positiveBtnMsg = "OK"
positiveBtnMsg = "Try again"
) {

action?.invoke()
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.recipeappiti.core.util

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities

object SystemChecks {
fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false
return activeNetwork.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class DataViewModel(
private val _isFavourite = MutableLiveData<Boolean>()
val isFavourite: LiveData<Boolean> get() = _isFavourite

private val _isSubscribed = MutableLiveData<Boolean>()
val isSubscribed: LiveData<Boolean> get() = _isSubscribed

private val _recipes = MutableLiveData<MutableList<Meal>>()
val recipes: LiveData<MutableList<Meal>> get() = _recipes

Expand All @@ -39,6 +42,7 @@ class DataViewModel(
_categorySearch.value = null
_mainCuisine.value = null
loadFavoriteItems()
checkSubscription()
}

fun setCuisines(cuisines: List<String>) {
Expand Down Expand Up @@ -88,6 +92,24 @@ class DataViewModel(
_isFavourite.value = currentFavouriteState ?: false
}

fun updateSubscriptionState(subscribed: Boolean) {
viewModelScope.launch {
userRepository.updateSubscriptionState(subscribed)
}.invokeOnCompletion {
checkSubscription()
}
}

fun checkSubscription() {
viewModelScope.launch {
val isSubscribed = userRepository.checkSubscriptionState()
when (isSubscribed) {
true -> _isSubscribed.value = true
false -> _isSubscribed.value = false
}
}
}

fun updateSearchCategory(category: String?) {
_categorySearch.value = category
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import com.example.recipeappiti.core.model.local.source.UserDatabase
import com.example.recipeappiti.core.model.remote.Meal
import com.example.recipeappiti.core.model.remote.repository.MealRepositoryImpl
import com.example.recipeappiti.core.model.remote.source.RemoteGsonDataImpl
import com.example.recipeappiti.core.util.CreateMaterialAlertDialogBuilder.createMaterialAlertDialogBuilderOk
import com.example.recipeappiti.core.util.SystemChecks
import com.example.recipeappiti.core.viewmodel.DataViewModel
import com.example.recipeappiti.core.viewmodel.DataViewModelFactory
import com.example.recipeappiti.details.view.adapters.IngredientsRecyclerViewAdapter
Expand Down Expand Up @@ -111,8 +113,7 @@ class RecipeDetailFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)

initViews()
initObservers()
initListeners()
checkConnection()
}

private fun initViews() {
Expand Down Expand Up @@ -143,7 +144,6 @@ class RecipeDetailFragment : Fragment() {
instructionsText = requireView().findViewById(R.id.instructionsText)

bottomNavigationView.visibility = View.GONE

}

private fun initListeners() {
Expand All @@ -165,7 +165,6 @@ class RecipeDetailFragment : Fragment() {
}

private fun initObservers() {

dataViewModel.itemDetails.observe(viewLifecycleOwner) { id ->
recipeId = id
changeFavouriteState(recipeId, false)
Expand Down Expand Up @@ -252,6 +251,22 @@ class RecipeDetailFragment : Fragment() {
youtubePlayerView.initialize(youtubePlayerListener, iFramePlayerOptions)
}

private fun checkConnection() {
if (!SystemChecks.isNetworkAvailable(requireContext())) {
createMaterialAlertDialogBuilderOk(
requireContext(),
"No Internet Connection",
"Please check your internet connection and try again",
"Retry",
) {
checkConnection()
}
} else {
initObservers()
initListeners()
}
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.recipeappiti.R

class IngredientsRecyclerViewAdapter :
RecyclerView.Adapter<IngredientsRecyclerViewAdapter.ViewHolder>() {
private var data: List<String> = emptyList()

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(android.R.id.text1)
val textView: TextView = itemView.findViewById(R.id.listText)
}

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val inflater: LayoutInflater = LayoutInflater.from(parent.context)
val view: View = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
val view: View = inflater.inflate(R.layout.simple_list_text, parent, false)
return ViewHolder(view)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import com.example.recipeappiti.R
import com.example.recipeappiti.core.model.remote.Category

class AdapterRVCategories(
private val categories: List<Category>,
private var categories: List<Category>,
private val goToSearch: ((id: String) -> Unit)? = null
) :
RecyclerView.Adapter<AdapterRVCategories.CategoryViewHolder>() {
) : RecyclerView.Adapter<AdapterRVCategories.CategoryViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder {
val view = LayoutInflater.from(parent.context)
Expand All @@ -33,15 +32,19 @@ class AdapterRVCategories(
.into(imageView)

itemView.setOnClickListener { goToSearch?.let { it(category.strCategory) } }

}
}

override fun getItemCount(): Int = categories.size

fun submitList(newCategories: List<Category>) {
categories = newCategories
notifyDataSetChanged()
}

class CategoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.item_category_image)
val textView: TextView = itemView.findViewById(R.id.item_category_title)

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import com.example.recipeappiti.R
import com.example.recipeappiti.core.model.remote.Meal

class AdapterRVItemMeal(
private val meals: List<Meal>,
private var meals: List<Meal>,
private val goToDetails: ((id: String) -> Unit)? = null
) :
RecyclerView.Adapter<AdapterRVItemMeal.MealViewHolder>() {
) : RecyclerView.Adapter<AdapterRVItemMeal.MealViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MealViewHolder {
val view = LayoutInflater.from(parent.context)
Expand All @@ -25,7 +24,6 @@ class AdapterRVItemMeal(
override fun onBindViewHolder(holder: MealViewHolder, position: Int) {
val meal = meals[position]


holder.titleView.text = formatDescription(meal.strMeal)

Glide.with(holder.itemView.context)
Expand All @@ -34,11 +32,15 @@ class AdapterRVItemMeal(
.into(holder.imageView)

holder.imageView.setOnClickListener {

goToDetails?.let { it(meal.idMeal) }

}
}

override fun getItemCount(): Int = meals.size

fun submitList(newMeals: List<Meal>) {
meals = newMeals
notifyDataSetChanged()
}

private fun formatDescription(
Expand All @@ -53,8 +55,6 @@ class AdapterRVItemMeal(
}
}

override fun getItemCount(): Int = meals.size

class MealViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.item_image)
val titleView: TextView = itemView.findViewById(R.id.item_title)
Expand Down
Loading

0 comments on commit 0ab89e1

Please sign in to comment.