Persistance of competitions in favorites achieve
continuous-integration/drone/push Build is passing Details

For_Me_Teams_Search
Emre KARTAL 2 years ago
parent 4e195b5115
commit e0d5e666f3

@ -1,6 +1,7 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
} }
android { android {
@ -49,7 +50,10 @@ dependencies {
// Room // Room
implementation 'androidx.room:room-runtime:2.5.1' implementation 'androidx.room:room-runtime:2.5.1'
implementation 'androidx.room:room-ktx: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.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0' implementation 'com.google.android.material:material:1.8.0'

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name=".application.ScorItApplication"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"

@ -1,11 +1,6 @@
package uca.iut.clermont.api package uca.iut.clermont.api
import AreaManager
import CompetitionsManager
import DataManager
import MatchesManager
import PeopleManager
import TeamsManager
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory

@ -0,0 +1,10 @@
package uca.iut.clermont.application
import android.app.Application
import uca.iut.clermont.data.BDD
class ScorItApplication: Application() {
val db: BDD by lazy { BDD.getInstance(this) }
}

@ -0,0 +1,30 @@
package uca.iut.clermont.converters
import androidx.room.TypeConverter
import com.google.gson.Gson
import uca.iut.clermont.model.Area
import uca.iut.clermont.model.Season
class Converters {
@TypeConverter
fun fromJson(json: String): Season {
return Gson().fromJson(json, Season::class.java)
}
@TypeConverter
fun toJson(season: Season): String {
return Gson().toJson(season)
}
@TypeConverter
fun fromJsonArea(json: String): Area {
return Gson().fromJson(json, Area::class.java)
}
@TypeConverter
fun toJson(area: Area): String {
return Gson().toJson(area)
}
}

@ -1,13 +1,13 @@
package uca.iut.clermont.data package uca.iut.clermont.data
import android.content.Context import android.content.Context
import androidx.room.Database import androidx.room.*
import androidx.room.Room import uca.iut.clermont.converters.Converters
import androidx.room.RoomDatabase
import uca.iut.clermont.data.dao.CompetitionDao import uca.iut.clermont.data.dao.CompetitionDao
import uca.iut.clermont.model.Competition import uca.iut.clermont.model.Competition
@Database(entities = arrayOf(Competition::class), version = 1) @Database(entities = arrayOf(Competition::class), version = 1)
@TypeConverters(Converters::class)
abstract class BDD : RoomDatabase() { abstract class BDD : RoomDatabase() {
abstract fun competitionDao(): CompetitionDao abstract fun competitionDao(): CompetitionDao
@ -24,6 +24,7 @@ abstract class BDD : RoomDatabase() {
"ScorItDB" "ScorItDB"
).build() ).build()
INSTANCE = db INSTANCE = db
INSTANCE!!
} }
} }

@ -1,11 +1,6 @@
package uca.iut.clermont.data package uca.iut.clermont.data
import AreaManager
import CompetitionsManager
import DataManager
import MatchesManager
import PeopleManager
import TeamsManager
import uca.iut.clermont.model.* import uca.iut.clermont.model.*
import java.util.* import java.util.*

@ -13,10 +13,13 @@ interface CompetitionDao {
@Delete @Delete
fun deleteCompetition(competition: Competition) fun deleteCompetition(competition: Competition)
@Query("SELECT * FROM competition") @Query("SELECT * FROM competitions")
fun getAllCompetitions(): Flow<List<Competition>> fun getAllCompetitions(): Flow<List<Competition>>
@Insert @Insert
fun insertCompetition(competition: Competition) fun insertCompetition(competition: Competition)
@Query("SELECT * FROM competitions WHERE id=:id")
fun getCompetitionById(id: Int): Flow<Competition?>
} }

@ -11,6 +11,6 @@ class Competition(
@ColumnInfo val code: String, @ColumnInfo val code: String,
@ColumnInfo val type: String, @ColumnInfo val type: String,
@ColumnInfo val emblem: String, @ColumnInfo val emblem: String,
@ColumnInfo val currentSeason: Season, val currentSeason: Season,
val area: Area val area: Area
) )

@ -1,4 +1,4 @@
import uca.iut.clermont.model.* package uca.iut.clermont.model
abstract class DataManager { abstract class DataManager {
abstract val areaMgr: AreaManager abstract val areaMgr: AreaManager

@ -15,9 +15,11 @@ import uca.iut.clermont.R
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import uca.iut.clermont.application.ScorItApplication
import uca.iut.clermont.model.Competition import uca.iut.clermont.model.Competition
import uca.iut.clermont.view.adapter.MatchesAdapter import uca.iut.clermont.view.adapter.MatchesAdapter
import uca.iut.clermont.view.viewModel.DetailViewModel import uca.iut.clermont.view.viewModel.DetailViewModel
import uca.iut.clermont.view.viewModel.ViewModelFactory
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -25,8 +27,9 @@ class DetailFragment : Fragment() {
private var isLiked = false private var isLiked = false
private lateinit var competition: Competition 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( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -36,6 +39,7 @@ class DetailFragment : Fragment() {
val view = inflater.inflate(R.layout.fragment_detail, container, false) val view = inflater.inflate(R.layout.fragment_detail, container, false)
val likeButton = view.findViewById<ImageButton>(R.id.buttonLike)
val id = arguments?.getInt("idItem")!! val id = arguments?.getInt("idItem")!!
viewModel.competition.observe(viewLifecycleOwner, Observer { comp -> 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 -> viewModel.competitionMatches.observe(viewLifecycleOwner, Observer { competitions ->
competitions?.let { competitions?.let {
initRecyclerView(view) initRecyclerView(view)
@ -61,14 +83,12 @@ class DetailFragment : Fragment() {
} }
}) })
viewModel.loadMatches(id) viewModel.loadMatches(id)
return view; return view;
} }
private fun initializeView(view: View) { private fun initializeView(view: View) {
val button = view.findViewById<ImageButton>(R.id.buttonLike)
val buttonExit = view.findViewById<ImageButton>(R.id.buttonExit) val buttonExit = view.findViewById<ImageButton>(R.id.buttonExit)
val imageHeader = view.findViewById<ImageView>(R.id.imageDetail) val imageHeader = view.findViewById<ImageView>(R.id.imageDetail)
val titleHeader = view.findViewById<TextView>(R.id.title) val titleHeader = view.findViewById<TextView>(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) Glide.with(view.context)
.load(competition.emblem) .load(competition.emblem)
.error(R.drawable.imagenotfound) .error(R.drawable.imagenotfound)
@ -126,6 +141,5 @@ class DetailFragment : Fragment() {
) )
} }
} }
} }
} }

@ -14,13 +14,20 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import uca.iut.clermont.R import uca.iut.clermont.R
import uca.iut.clermont.application.ScorItApplication
import uca.iut.clermont.model.Competition import uca.iut.clermont.model.Competition
import uca.iut.clermont.model.Match
import uca.iut.clermont.view.adapter.CompetitionsAdapter import uca.iut.clermont.view.adapter.CompetitionsAdapter
import uca.iut.clermont.view.viewModel.FavoriteViewModel import uca.iut.clermont.view.viewModel.FavoriteViewModel
import uca.iut.clermont.view.viewModel.ViewModelFactory
class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener { class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
private val viewModel: FavoriteViewModel by viewModels() private var favorites: List<Competition> = mutableListOf()
private val viewModel: FavoriteViewModel by viewModels {
ViewModelFactory((requireActivity().application as ScorItApplication).db.competitionDao())
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -28,14 +35,14 @@ class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
val view = inflater.inflate(R.layout.fragment_favorite, container, false) val view = inflater.inflate(R.layout.fragment_favorite, container, false)
viewModel.competitions.observe(viewLifecycleOwner, Observer { competitions ->
viewModel.getAllCompetitions().observe(viewLifecycleOwner, Observer { competitions ->
competitions?.let { competitions?.let {
favorites = competitions
initRecyclerView(view, competitions, this) initRecyclerView(view, competitions, this)
} }
}) })
viewModel.loadCompetitions()
initializeView(view) initializeView(view)
return view return view
@ -71,11 +78,11 @@ class FavoriteFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
} }
override fun onItemClick(position: Int) { override fun onItemClick(position: Int) {
val competitions = viewModel.competitions.value!!
val bundle = bundleOf( val bundle = bundleOf(
"idItem" to competitions[position].id, "idItem" to favorites[position].id,
"fragmentId" to R.id.favoriteFragment "fragmentId" to R.id.favoriteFragment
) )
findNavController().navigate(R.id.action_favoriteFragment_to_detailFragment, bundle) findNavController().navigate(R.id.action_favoriteFragment_to_detailFragment, bundle)
} }
} }

@ -49,7 +49,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
viewModel.matches.observe(viewLifecycleOwner, Observer { matches -> viewModel.matches.observe(viewLifecycleOwner, Observer { matches ->
matches?.let { matches?.let {
if (it.isNotEmpty()) { if (it.isNotEmpty()) {
initRecyclerView(view, it, this) initRecyclerView(view, it)
} else { } else {
text.setText(R.string.noMatches) text.setText(R.string.noMatches)
} }
@ -76,6 +76,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
private val textWatcher = object : TextWatcher { private val textWatcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { 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) { 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?) { override fun afterTextChanged(s: Editable?) {
// No need for the function
} }
} }
@ -98,8 +100,7 @@ class HomeFragment : Fragment(), CompetitionsAdapter.OnItemClickListener {
private fun initRecyclerView( private fun initRecyclerView(
view: View, view: View,
matches: List<Match>, matches: List<Match>
listener: CompetitionsAdapter.OnItemClickListener
) { ) {
val recyclerViewMatches = view.findViewById<RecyclerView>(R.id.listRecentsMatches) val recyclerViewMatches = view.findViewById<RecyclerView>(R.id.listRecentsMatches)
with(recyclerViewMatches) { with(recyclerViewMatches) {

@ -3,35 +3,46 @@ package uca.iut.clermont.view.viewModel
import android.util.Log import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import uca.iut.clermont.api.ApiManager import uca.iut.clermont.api.ApiManager
import uca.iut.clermont.data.dao.CompetitionDao
import uca.iut.clermont.model.Competition import uca.iut.clermont.model.Competition
import uca.iut.clermont.model.Match import uca.iut.clermont.model.Match
import java.util.* import java.util.*
class DetailViewModel( class DetailViewModel(
//val dao: CompetitionDao val dao: CompetitionDao
) : ViewModel() { ) : ViewModel() {
val ERROR = "too many requests"
val manager = ApiManager() val manager = ApiManager()
val competition = MutableLiveData<Competition?>() val competition = MutableLiveData<Competition?>()
val competitionMatches = MutableLiveData<List<Match>>() val competitionMatches = MutableLiveData<List<Match>>()
val nbCompetitionMatches = MutableLiveData<Int>() val nbCompetitionMatches = MutableLiveData<Int>()
val isFavorite = MutableLiveData<Boolean>()
/*fun insertCompetition(competition: Competition) = fun insertCompetition(competition: Competition) =
viewModelScope.launch { viewModelScope.launch(Dispatchers.IO) {
dao.insertCompetition(competition) 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 { fun loadCurrentCompetition(id: Int) = viewModelScope.launch {
try { try {
val result = manager.competitionsMgr.getItemById(id) val result = manager.competitionsMgr.getItemById(id)
competition.value = result competition.value = result
} catch (e: HttpException) { } 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 } .sortedBy { it.competition.name }
.sortedByDescending { it.date } .sortedByDescending { it.date }
} catch (e: HttpException) { } catch (e: HttpException) {
Log.d(e.toString(), ": too many requests") Log.d(e.toString(), ERROR)
} }
} }
@ -52,7 +63,7 @@ class DetailViewModel(
try { try {
nbCompetitionMatches.value = competitionMatches.value?.size nbCompetitionMatches.value = competitionMatches.value?.size
} catch (e: HttpException) { } catch (e: HttpException) {
Log.d(e.toString(), ": too many requests") Log.d(e.toString(), ERROR)
} }
} }
} }

@ -1,25 +1,11 @@
package uca.iut.clermont.view.viewModel package uca.iut.clermont.view.viewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.asLiveData
import kotlinx.coroutines.launch import uca.iut.clermont.data.dao.CompetitionDao
import uca.iut.clermont.api.ApiManager
import uca.iut.clermont.model.Competition
class FavoriteViewModel( class FavoriteViewModel(
//val dao: CompetitionDao val dao: CompetitionDao
) : ViewModel() { ) : ViewModel() {
fun getAllCompetitions() = dao.getAllCompetitions().asLiveData()
val manager = ApiManager()
val competitions = MutableLiveData<List<Competition>>()
//fun getAllCompetitions() = dao.getAllCompetitions()
//.isLiveDate()
fun loadCompetitions() = viewModelScope.launch {
val result = manager.competitionsMgr.getItems()
competitions.value = result
}
} }

@ -13,6 +13,7 @@ import java.util.*
class HomeViewModel : ViewModel() { class HomeViewModel : ViewModel() {
val ERROR = "too many requests"
val manager = ApiManager() val manager = ApiManager()
val matches = MutableLiveData<List<Match>?>() val matches = MutableLiveData<List<Match>?>()
val competitions = MutableLiveData<List<Competition>>() val competitions = MutableLiveData<List<Competition>>()
@ -25,7 +26,7 @@ class HomeViewModel : ViewModel() {
.sortedBy { it.competition.name } .sortedBy { it.competition.name }
.sortedByDescending { it.date } .sortedByDescending { it.date }
} catch (e: HttpException) { } 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() val result = manager.competitionsMgr.getItems()
competitions.value = result competitions.value = result
} catch (e: HttpException) { } catch (e: HttpException) {
Log.d(e.toString(),": too many requests") Log.d(e.toString(),ERROR)
} }
} }

@ -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 <T : ViewModel> create(modelClass: Class<T>): 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")
}
}
Loading…
Cancel
Save