From e0d5e666f3bf04b57a8b7d85fab405268714dc93 Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Mon, 10 Apr 2023 21:50:33 +0200 Subject: [PATCH] Persistance of competitions in favorites achieve :white_check_mark: --- src/app/build.gradle | 4 +++ src/app/src/main/AndroidManifest.xml | 1 + .../java/uca/iut/clermont/api/ApiManager.kt | 7 +--- .../clermont/application/ScorItApplication.kt | 10 ++++++ .../uca/iut/clermont/converters/Converters.kt | 30 ++++++++++++++++ .../main/java/uca/iut/clermont/data/BDD.kt | 7 ++-- .../java/uca/iut/clermont/data/StubData.kt | 7 +--- .../iut/clermont/data/dao/CompetitionDao.kt | 5 ++- .../uca/iut/clermont/model/Competition.kt | 2 +- .../uca/iut/clermont/model/DataManager.kt | 2 +- .../uca/iut/clermont/view/DetailFragment.kt | 34 +++++++++++++------ .../uca/iut/clermont/view/FavoriteFragment.kt | 19 +++++++---- .../uca/iut/clermont/view/HomeFragment.kt | 7 ++-- .../view/viewModel/DetailViewModel.kt | 25 ++++++++++---- .../view/viewModel/FavoriteViewModel.kt | 22 +++--------- .../clermont/view/viewModel/HomeViewModel.kt | 5 +-- .../view/viewModel/ViewModelFactory.kt | 19 +++++++++++ 17 files changed, 142 insertions(+), 64 deletions(-) create mode 100644 src/app/src/main/java/uca/iut/clermont/application/ScorItApplication.kt create mode 100644 src/app/src/main/java/uca/iut/clermont/converters/Converters.kt create mode 100644 src/app/src/main/java/uca/iut/clermont/view/viewModel/ViewModelFactory.kt diff --git a/src/app/build.gradle b/src/app/build.gradle index 0876475..fceb360 100644 --- a/src/app/build.gradle +++ b/src/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' } android { @@ -49,7 +50,10 @@ dependencies { // Room implementation 'androidx.room:room-runtime:2.5.1' implementation 'androidx.room:room-ktx:2.5.1' + kapt "androidx.room:room-compiler:2.5.1" + + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' diff --git a/src/app/src/main/AndroidManifest.xml b/src/app/src/main/AndroidManifest.xml index fc1af9b..8208cf0 100644 --- a/src/app/src/main/AndroidManifest.xml +++ b/src/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ > @Insert fun insertCompetition(competition: Competition) + @Query("SELECT * FROM competitions WHERE id=:id") + fun getCompetitionById(id: Int): Flow + } \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/model/Competition.kt b/src/app/src/main/java/uca/iut/clermont/model/Competition.kt index ade30ee..6ee6350 100644 --- a/src/app/src/main/java/uca/iut/clermont/model/Competition.kt +++ b/src/app/src/main/java/uca/iut/clermont/model/Competition.kt @@ -11,6 +11,6 @@ class Competition( @ColumnInfo val code: String, @ColumnInfo val type: String, @ColumnInfo val emblem: String, - @ColumnInfo val currentSeason: Season, + val currentSeason: Season, val area: Area ) \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/model/DataManager.kt b/src/app/src/main/java/uca/iut/clermont/model/DataManager.kt index 0910fc8..a7db6b9 100644 --- a/src/app/src/main/java/uca/iut/clermont/model/DataManager.kt +++ b/src/app/src/main/java/uca/iut/clermont/model/DataManager.kt @@ -1,4 +1,4 @@ -import uca.iut.clermont.model.* +package uca.iut.clermont.model abstract class DataManager { abstract val areaMgr: AreaManager diff --git a/src/app/src/main/java/uca/iut/clermont/view/DetailFragment.kt b/src/app/src/main/java/uca/iut/clermont/view/DetailFragment.kt index 6aa8f54..5e962b7 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/DetailFragment.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/DetailFragment.kt @@ -15,9 +15,11 @@ import uca.iut.clermont.R import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import uca.iut.clermont.application.ScorItApplication import uca.iut.clermont.model.Competition import uca.iut.clermont.view.adapter.MatchesAdapter import uca.iut.clermont.view.viewModel.DetailViewModel +import uca.iut.clermont.view.viewModel.ViewModelFactory import java.text.SimpleDateFormat import java.util.* @@ -25,8 +27,9 @@ class DetailFragment : Fragment() { private var isLiked = false private lateinit var competition: Competition - private val viewModel: DetailViewModel by viewModels() - + private val viewModel: DetailViewModel by viewModels { + ViewModelFactory((requireActivity().application as ScorItApplication).db.competitionDao()) + } override fun onCreateView( inflater: LayoutInflater, @@ -36,6 +39,7 @@ class DetailFragment : Fragment() { val view = inflater.inflate(R.layout.fragment_detail, container, false) + val likeButton = view.findViewById(R.id.buttonLike) val id = arguments?.getInt("idItem")!! viewModel.competition.observe(viewLifecycleOwner, Observer { comp -> @@ -54,6 +58,24 @@ class DetailFragment : Fragment() { } }) + viewModel.check(id).observe(viewLifecycleOwner, Observer { competition -> + competition?.let { + isLiked = true + likeButton.setImageResource(R.drawable.full_like) + } + }) + + likeButton.setOnClickListener { + if (isLiked) { + viewModel.deleteCompetition(competition) + likeButton.setImageResource(R.drawable.empty_like) + } else { + viewModel.insertCompetition(competition) + likeButton.setImageResource(R.drawable.full_like) + } + isLiked = !isLiked + } + viewModel.competitionMatches.observe(viewLifecycleOwner, Observer { competitions -> competitions?.let { initRecyclerView(view) @@ -61,14 +83,12 @@ class DetailFragment : Fragment() { } }) - viewModel.loadMatches(id) return view; } private fun initializeView(view: View) { - val button = view.findViewById(R.id.buttonLike) val buttonExit = view.findViewById(R.id.buttonExit) val imageHeader = view.findViewById(R.id.imageDetail) val titleHeader = view.findViewById(R.id.title) @@ -83,11 +103,6 @@ class DetailFragment : Fragment() { } } - button.setOnClickListener { - isLiked = !isLiked - button.setImageResource(if (isLiked) R.drawable.full_like else R.drawable.empty_like) - } - Glide.with(view.context) .load(competition.emblem) .error(R.drawable.imagenotfound) @@ -126,6 +141,5 @@ class DetailFragment : Fragment() { ) } } - } } \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/view/FavoriteFragment.kt b/src/app/src/main/java/uca/iut/clermont/view/FavoriteFragment.kt index 3627133..3c776b8 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/FavoriteFragment.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/FavoriteFragment.kt @@ -14,13 +14,20 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import uca.iut.clermont.R +import uca.iut.clermont.application.ScorItApplication import uca.iut.clermont.model.Competition +import uca.iut.clermont.model.Match import uca.iut.clermont.view.adapter.CompetitionsAdapter import uca.iut.clermont.view.viewModel.FavoriteViewModel +import uca.iut.clermont.view.viewModel.ViewModelFactory class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { - private val viewModel: FavoriteViewModel by viewModels() + private var favorites: List = mutableListOf() + + private val viewModel: FavoriteViewModel by viewModels { + ViewModelFactory((requireActivity().application as ScorItApplication).db.competitionDao()) + } override fun onCreateView( inflater: LayoutInflater, @@ -28,14 +35,14 @@ class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_favorite, container, false) - viewModel.competitions.observe(viewLifecycleOwner, Observer { competitions -> + + viewModel.getAllCompetitions().observe(viewLifecycleOwner, Observer { competitions -> competitions?.let { + favorites = competitions initRecyclerView(view, competitions, this) } }) - viewModel.loadCompetitions() - initializeView(view) return view @@ -71,11 +78,11 @@ class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { } override fun onItemClick(position: Int) { - val competitions = viewModel.competitions.value!! val bundle = bundleOf( - "idItem" to competitions[position].id, + "idItem" to favorites[position].id, "fragmentId" to R.id.favoriteFragment ) findNavController().navigate(R.id.action_favoriteFragment_to_detailFragment, bundle) } + } \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/view/HomeFragment.kt b/src/app/src/main/java/uca/iut/clermont/view/HomeFragment.kt index e035845..625ba1d 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/HomeFragment.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/HomeFragment.kt @@ -49,7 +49,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { viewModel.matches.observe(viewLifecycleOwner, Observer { matches -> matches?.let { if (it.isNotEmpty()) { - initRecyclerView(view, it, this) + initRecyclerView(view, it) } else { text.setText(R.string.noMatches) } @@ -76,6 +76,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { private val textWatcher = object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + // No need for the function } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { @@ -83,6 +84,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { } override fun afterTextChanged(s: Editable?) { + // No need for the function } } @@ -98,8 +100,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { private fun initRecyclerView( view: View, - matches: List, - listener: CompetitionsAdapter.OnItemClickListener + matches: List ) { val recyclerViewMatches = view.findViewById(R.id.listRecentsMatches) with(recyclerViewMatches) { diff --git a/src/app/src/main/java/uca/iut/clermont/view/viewModel/DetailViewModel.kt b/src/app/src/main/java/uca/iut/clermont/view/viewModel/DetailViewModel.kt index 9e9f9e0..f6554e2 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/viewModel/DetailViewModel.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/viewModel/DetailViewModel.kt @@ -3,35 +3,46 @@ package uca.iut.clermont.view.viewModel import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import retrofit2.HttpException import uca.iut.clermont.api.ApiManager +import uca.iut.clermont.data.dao.CompetitionDao import uca.iut.clermont.model.Competition import uca.iut.clermont.model.Match import java.util.* class DetailViewModel( - //val dao: CompetitionDao + val dao: CompetitionDao ) : ViewModel() { + val ERROR = "too many requests" val manager = ApiManager() val competition = MutableLiveData() val competitionMatches = MutableLiveData>() val nbCompetitionMatches = MutableLiveData() + val isFavorite = MutableLiveData() - /*fun insertCompetition(competition: Competition) = - viewModelScope.launch { + fun insertCompetition(competition: Competition) = + viewModelScope.launch(Dispatchers.IO) { dao.insertCompetition(competition) } - */ + + fun deleteCompetition(competition: Competition) = + viewModelScope.launch(Dispatchers.IO) { + dao.deleteCompetition(competition) + } + + fun check(id: Int) = dao.getCompetitionById(id).asLiveData() fun loadCurrentCompetition(id: Int) = viewModelScope.launch { try { val result = manager.competitionsMgr.getItemById(id) competition.value = result } catch (e: HttpException) { - Log.d(e.toString(), ": too many requests") + Log.d(e.toString(), ERROR) } } @@ -44,7 +55,7 @@ class DetailViewModel( .sortedBy { it.competition.name } .sortedByDescending { it.date } } catch (e: HttpException) { - Log.d(e.toString(), ": too many requests") + Log.d(e.toString(), ERROR) } } @@ -52,7 +63,7 @@ class DetailViewModel( try { nbCompetitionMatches.value = competitionMatches.value?.size } catch (e: HttpException) { - Log.d(e.toString(), ": too many requests") + Log.d(e.toString(), ERROR) } } } \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/view/viewModel/FavoriteViewModel.kt b/src/app/src/main/java/uca/iut/clermont/view/viewModel/FavoriteViewModel.kt index f84c449..29a4055 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/viewModel/FavoriteViewModel.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/viewModel/FavoriteViewModel.kt @@ -1,25 +1,11 @@ package uca.iut.clermont.view.viewModel -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.launch -import uca.iut.clermont.api.ApiManager -import uca.iut.clermont.model.Competition +import androidx.lifecycle.asLiveData +import uca.iut.clermont.data.dao.CompetitionDao class FavoriteViewModel( - //val dao: CompetitionDao + val dao: CompetitionDao ) : ViewModel() { - - val manager = ApiManager() - val competitions = MutableLiveData>() - - //fun getAllCompetitions() = dao.getAllCompetitions() - //.isLiveDate() - - fun loadCompetitions() = viewModelScope.launch { - val result = manager.competitionsMgr.getItems() - competitions.value = result - } - + fun getAllCompetitions() = dao.getAllCompetitions().asLiveData() } \ No newline at end of file diff --git a/src/app/src/main/java/uca/iut/clermont/view/viewModel/HomeViewModel.kt b/src/app/src/main/java/uca/iut/clermont/view/viewModel/HomeViewModel.kt index 1e49caf..2acfcf5 100644 --- a/src/app/src/main/java/uca/iut/clermont/view/viewModel/HomeViewModel.kt +++ b/src/app/src/main/java/uca/iut/clermont/view/viewModel/HomeViewModel.kt @@ -13,6 +13,7 @@ import java.util.* class HomeViewModel : ViewModel() { + val ERROR = "too many requests" val manager = ApiManager() val matches = MutableLiveData?>() val competitions = MutableLiveData>() @@ -25,7 +26,7 @@ class HomeViewModel : ViewModel() { .sortedBy { it.competition.name } .sortedByDescending { it.date } } catch (e: HttpException) { - Log.d(e.toString(),": too many requests") + Log.d(e.toString(),ERROR) } } @@ -34,7 +35,7 @@ class HomeViewModel : ViewModel() { val result = manager.competitionsMgr.getItems() competitions.value = result } catch (e: HttpException) { - Log.d(e.toString(),": too many requests") + Log.d(e.toString(),ERROR) } } diff --git a/src/app/src/main/java/uca/iut/clermont/view/viewModel/ViewModelFactory.kt b/src/app/src/main/java/uca/iut/clermont/view/viewModel/ViewModelFactory.kt new file mode 100644 index 0000000..64aaac0 --- /dev/null +++ b/src/app/src/main/java/uca/iut/clermont/view/viewModel/ViewModelFactory.kt @@ -0,0 +1,19 @@ +package uca.iut.clermont.view.viewModel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import uca.iut.clermont.data.dao.CompetitionDao + +class ViewModelFactory(private val dao: CompetitionDao): ViewModelProvider.Factory { + + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(FavoriteViewModel::class.java)){ + return FavoriteViewModel(dao) as T + } + if (modelClass.isAssignableFrom(DetailViewModel::class.java)){ + return DetailViewModel(dao) as T + } + throw IllegalArgumentException("Unknown viewModel class") + } + +} \ No newline at end of file