From 724e6cb75c47a1074b54003b869408cd066b5e5b Mon Sep 17 00:00:00 2001 From: Jordan Artzet Date: Sun, 5 Feb 2023 21:18:27 +0100 Subject: [PATCH] :construction: add the tv show request and display the data in the tvshow cateogry --- .../api/MovieApplicationAPI.kt | 4 +- .../api/dtos/MediaResultDTO.kt | 2 +- .../model/media/tvshow/TvShow.kt | 72 +++++++++++++++---- .../repository/TVShowRepository.kt | 43 ----------- .../repository/TvShowRepository.kt | 29 ++++++++ .../ui/activity/MainActivity.kt | 2 +- .../ui/adapter/MovieAdapter.kt | 5 +- .../ui/adapter/TvShowAdapter.kt | 48 +++++++++++++ .../ui/fragments/MoviesFragment.kt | 2 +- .../ui/fragments/TvShowsFragment.kt | 59 ++++++++++++++- .../movieapplication/ui/viewmodel/MoviesVM.kt | 8 ++- .../movieapplication/ui/viewmodel/TvShowVM.kt | 34 +++++++++ .../pm/movieapplication/utils/Constants.kt | 1 + .../utils/MediaResultMapper.kt | 6 +- .../src/main/res/layout/fragment_movies.xml | 2 +- .../src/main/res/layout/fragment_tv_shows.xml | 48 ++++++++++--- .../main/res/layout/item_tv_show_category.xml | 67 +++++++++++++++++ Sources/app/src/main/res/values/strings.xml | 7 ++ 18 files changed, 358 insertions(+), 81 deletions(-) delete mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TVShowRepository.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TvShowRepository.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/TvShowAdapter.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/TvShowVM.kt create mode 100644 Sources/app/src/main/res/layout/item_tv_show_category.xml diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/MovieApplicationAPI.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/MovieApplicationAPI.kt index 13efeba..5b9350a 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/MovieApplicationAPI.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/MovieApplicationAPI.kt @@ -28,8 +28,8 @@ interface MovieApplicationAPI { // TvShow - @GET - fun getPopularTvShow(@Query("api_key") apiKey : String = API_KEY, @Query("page") page : Int = 1) : Call + @GET("tv/popular") + suspend fun getPopularTvShow(@Query("api_key") apiKey : String = API_KEY, @Query("page") page : Int = 1) : Response @GET("trending/{media_type}/{time_window}") diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt index b9b56af..2a979af 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt @@ -8,7 +8,7 @@ data class MediaResultDTO( @Json(name = "poster_path") val posterPath : String?, - val adult : Boolean, + val adult : Boolean?, val overview : String, @Json(name = "first_air_date") val firstAirDate : String?, diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt index b9ac31a..0b698dc 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt @@ -1,20 +1,62 @@ package fr.iut.pm.movieapplication.model.media.tvshow -class TvShow( - val posterPath: String?, - val popularity: Double, - val id: Int, - val backdropPath: String, - val voteAverage: Double, - val overview: String, - val firstAirDate: String?, - val originCountry: List, - val genreIds: List, - val originalLanguage: String, - val voteCount: Int, - val name: String, - val originalName: String, - val mediaType: String = "tv", +open class TvShow( + open val posterPath: String?, + open val popularity: Double, + open val id: Int, + open val backdropPath: String, + open val voteAverage: Double, + open val overview: String, + open val firstAirDate: String?, + open val originCountry: List, + open val genreIds: List, + open val originalLanguage: String, + open val voteCount: Int, + open val name: String, + open val originalName: String, + open val mediaType: String = "tv", ) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as TvShow + + if (posterPath != other.posterPath) return false + if (popularity != other.popularity) return false + if (id != other.id) return false + if (backdropPath != other.backdropPath) return false + if (voteAverage != other.voteAverage) return false + if (overview != other.overview) return false + if (firstAirDate != other.firstAirDate) return false + if (originCountry != other.originCountry) return false + if (genreIds != other.genreIds) return false + if (originalLanguage != other.originalLanguage) return false + if (voteCount != other.voteCount) return false + if (name != other.name) return false + if (originalName != other.originalName) return false + if (mediaType != other.mediaType) return false + + return true + } + + override fun hashCode(): Int { + var result = posterPath?.hashCode() ?: 0 + result = 31 * result + popularity.hashCode() + result = 31 * result + id + result = 31 * result + backdropPath.hashCode() + result = 31 * result + voteAverage.hashCode() + result = 31 * result + overview.hashCode() + result = 31 * result + (firstAirDate?.hashCode() ?: 0) + result = 31 * result + originCountry.hashCode() + result = 31 * result + genreIds.hashCode() + result = 31 * result + originalLanguage.hashCode() + result = 31 * result + voteCount + result = 31 * result + name.hashCode() + result = 31 * result + originalName.hashCode() + result = 31 * result + mediaType.hashCode() + return result + } } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TVShowRepository.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TVShowRepository.kt deleted file mode 100644 index f2c1d4a..0000000 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TVShowRepository.kt +++ /dev/null @@ -1,43 +0,0 @@ -package fr.iut.pm.movieapplication.repository - -import android.util.Log -import fr.iut.pm.movieapplication.api.RetrofitInstance -import fr.iut.pm.movieapplication.api.dtos.PopularDTO -import fr.iut.pm.movieapplication.model.media.movie.Movie -import fr.iut.pm.movieapplication.model.media.tvshow.TvShow -import fr.iut.pm.movieapplication.utils.MediaResultMapper -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response - -class TVShowRepository { - -// fun getPopularTvShow(page : Int = 1 ,callback: (List) -> Unit ) { -// -// val listMovie : MutableList = mutableListOf() -// -// RetrofitInstance.api.getPopularMovies(page = page).enqueue(object : -// Callback { -// override fun onResponse(call: Call, response: Response) { -// if (response.isSuccessful) { -// Log.d("List :", response.body().toString()) -// val popularDTO = response.body() -// val listMoviesDTO = popularDTO?.results -// listMoviesDTO?.forEach { -// -// val tvShow = MediaResultMapper.mapToTvShow(it) -// listMovie.add(tvShow) -// Log.d("Movie ", tvShow.name ) -// } -// -// } -// callback(listMovie) -// } -// -// override fun onFailure(call: Call, t: Throwable) { -// Log.d("Error failure", t.message.toString()) -// } -// -// }) -// } -} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TvShowRepository.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TvShowRepository.kt new file mode 100644 index 0000000..01e2e10 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TvShowRepository.kt @@ -0,0 +1,29 @@ +package fr.iut.pm.movieapplication.repository + +import android.util.Log +import fr.iut.pm.movieapplication.api.RetrofitInstance +import fr.iut.pm.movieapplication.model.media.tvshow.TvShow +import fr.iut.pm.movieapplication.utils.MediaResultMapper + +class TvShowRepository { + + suspend fun getPopularTvShow(page : Int = 1 ) : List { + + val listMovie : MutableList = mutableListOf() + + val response = RetrofitInstance.api.getPopularTvShow(page = page) + if (response.isSuccessful) { + Log.d("List :", response.body().toString()) + val popularDTO = response.body() + val listMoviesDTO = popularDTO?.results + listMoviesDTO?.forEach { + val tvShow = MediaResultMapper.mapToTvShow(it) + listMovie.add(tvShow) + Log.d("Movie ", tvShow.name ) + } + } + else Log.d("Error failure", response.message()) + + return listMovie + } +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/activity/MainActivity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/activity/MainActivity.kt index 30f886a..b27c2aa 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/activity/MainActivity.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/activity/MainActivity.kt @@ -40,7 +40,7 @@ class MainActivity : AppCompatActivity() { } R.id.series_page -> { - loadFragments(TvShowsFragment(this)) + loadFragments(TvShowsFragment()) return@setOnItemSelectedListener true } else -> false diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/MovieAdapter.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/MovieAdapter.kt index e19e4e0..24eed09 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/MovieAdapter.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/MovieAdapter.kt @@ -11,9 +11,9 @@ import fr.iut.pm.movieapplication.databinding.ItemMovieCategoryBinding import fr.iut.pm.movieapplication.model.media.movie.Movie import fr.iut.pm.movieapplication.utils.Constants -class MovieAdapter : ListAdapter(DiffUtilDogCallback) { +class MovieAdapter() : ListAdapter(DiffUtilMovieCallback) { - private object DiffUtilDogCallback : DiffUtil.ItemCallback() { + private object DiffUtilMovieCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: Movie, newItem: Movie) = oldItem.id == newItem.id override fun areContentsTheSame(oldItem: Movie, newItem: Movie) = oldItem == newItem } @@ -40,4 +40,5 @@ class MovieAdapter : ListAdapter(DiffUtilDogCall ViewHolder(ItemMovieCategoryBinding.inflate(LayoutInflater.from(parent.context))) override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(getItem(position)) + } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/TvShowAdapter.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/TvShowAdapter.kt new file mode 100644 index 0000000..e139b65 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/TvShowAdapter.kt @@ -0,0 +1,48 @@ +package fr.iut.pm.movieapplication.ui.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.net.toUri +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import coil.load +import fr.iut.pm.movieapplication.databinding.ItemTvShowCategoryBinding +import fr.iut.pm.movieapplication.model.media.tvshow.TvShow +import fr.iut.pm.movieapplication.utils.Constants + +class TvShowAdapter() : ListAdapter(DiffUtilTvShowCallback) { + + + private object DiffUtilTvShowCallback : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: TvShow, newItem: TvShow) = oldItem.id == newItem.id + + override fun areContentsTheSame(oldItem: TvShow, newItem: TvShow) = oldItem == newItem + } + + + class ViewHolder(private val binding : ItemTvShowCategoryBinding) + : RecyclerView.ViewHolder(binding.root){ + + val tvShow : TvShow? get() = binding.tvShow + + init { + itemView.setOnClickListener {} + } + + fun bind(tvShow : TvShow) { + binding.tvShow = tvShow + val imgUri = tvShow.posterPath?.let { (Constants.IMG_URL +it).toUri().buildUpon().scheme("https").build() } + binding.itemImage.load(imgUri) + binding.executePendingBindings() + } + + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TvShowAdapter.ViewHolder = + TvShowAdapter.ViewHolder(ItemTvShowCategoryBinding.inflate(LayoutInflater.from(parent.context))) + + override fun onBindViewHolder(holder: TvShowAdapter.ViewHolder, position: Int) = holder.bind(getItem(position)) + +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/MoviesFragment.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/MoviesFragment.kt index c4573f5..c0326ac 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/MoviesFragment.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/MoviesFragment.kt @@ -32,7 +32,7 @@ class MoviesFragment( ) adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - with(binding.categorySpinner) + with(binding.categoryMovieSpinner) { this.adapter = adapter onItemSelectedListener = object : AdapterView.OnItemSelectedListener { diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/TvShowsFragment.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/TvShowsFragment.kt index 4aba7f2..fe13393 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/TvShowsFragment.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/TvShowsFragment.kt @@ -1,15 +1,68 @@ package fr.iut.pm.movieapplication.ui.fragments import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import fr.iut.pm.movieapplication.R +import fr.iut.pm.movieapplication.databinding.FragmentTvShowsBinding import fr.iut.pm.movieapplication.ui.activity.MainActivity +import fr.iut.pm.movieapplication.ui.viewmodel.TvShowVM class TvShowsFragment( - private val context : MainActivity ) : Fragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + private val tvShowVM by viewModels() + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?) + : View { + val binding = FragmentTvShowsBinding.inflate(inflater) + + binding.tvShowVM = tvShowVM + binding.lifecycleOwner = viewLifecycleOwner + + val adapter = ArrayAdapter.createFromResource( + requireContext(), + R.array.tv_show_filter, + android.R.layout.simple_spinner_item + ) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + + with(binding.categoryTvShowSpinner) + { + this.adapter = adapter + onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, + view: View?, + position: Int, + id: Long + ) { + tvShowVM.getData(selectedItem.toString()) + } + + + override fun onNothingSelected(parent: AdapterView<*>?) { + TODO("Not yet implemented") + } + + } + } + + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + tvShowVM.getTvShowLiveData().observe(viewLifecycleOwner) { + tvShowVM.tvShowAdapter.submitList(it) + } } } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesVM.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesVM.kt index 126f2b3..69cf7cd 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesVM.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesVM.kt @@ -6,6 +6,8 @@ import androidx.recyclerview.widget.RecyclerView import fr.iut.pm.movieapplication.model.media.movie.Movie import fr.iut.pm.movieapplication.repository.MovieRepository import fr.iut.pm.movieapplication.ui.adapter.MovieAdapter +import fr.iut.pm.movieapplication.utils.Constants.Companion.MAX_PAGE +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class MoviesVM() : ViewModel() { @@ -43,11 +45,15 @@ class MoviesVM() : ViewModel() { if(lastVisibleItemPosition == totalItemCount -1) { ++currentPage - getMoreData(currentPage) + //1000 is the MAX_PAGE + if(currentPage <= MAX_PAGE) getMoreData(currentPage) } } } + /** + * Currrent page where the data are obtained + */ private var currentPage = 1 /** diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/TvShowVM.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/TvShowVM.kt new file mode 100644 index 0000000..33b1c4b --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/TvShowVM.kt @@ -0,0 +1,34 @@ +package fr.iut.pm.movieapplication.ui.viewmodel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import fr.iut.pm.movieapplication.model.media.tvshow.TvShow +import fr.iut.pm.movieapplication.repository.TvShowRepository +import fr.iut.pm.movieapplication.ui.adapter.TvShowAdapter +import kotlinx.coroutines.launch + +class TvShowVM : ViewModel() { + + private val tvShowRepository = TvShowRepository() + + private var tvShowLiveData : MutableLiveData> = MutableLiveData>() + fun getTvShowLiveData() : LiveData> = tvShowLiveData + + private var currentFilter : String = "" + val tvShowAdapter = TvShowAdapter() + + private var currentPage = 1 + + fun getData(filter : String) { + + currentFilter = filter + currentPage = 1 + when(currentFilter) { + "Populaires" -> viewModelScope.launch { + tvShowLiveData.postValue(tvShowRepository.getPopularTvShow()) + } + } + } +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Constants.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Constants.kt index 3bc70c1..37e050b 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Constants.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Constants.kt @@ -12,5 +12,6 @@ class Constants { //VIEW PAGINATION const val PAGE_SIZE = 20 + const val MAX_PAGE = 1000 } } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt index c15a018..0b58a33 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt @@ -12,7 +12,7 @@ object MediaResultMapper { posterPath = mediaResultDTO.posterPath, popularity = mediaResultDTO.popularity, id = mediaResultDTO.id, - backdropPath = mediaResultDTO.backdropPath!!, + backdropPath = mediaResultDTO.backdropPath ?: "", voteAverage = mediaResultDTO.voteAverage, overview = mediaResultDTO.overview, firstAirDate = mediaResultDTO.firstAirDate, @@ -28,7 +28,7 @@ object MediaResultMapper { fun mapToMovie(mediaResultDTO: MediaResultDTO): Movie { return Movie( posterPath = mediaResultDTO.posterPath, - adult = !mediaResultDTO.adult, + adult = mediaResultDTO.adult!!, overview = mediaResultDTO.overview, releaseDate = mediaResultDTO.releaseDate ?: "", genreIds = mediaResultDTO.genreIds, @@ -47,7 +47,7 @@ object MediaResultMapper { fun mapToMediaResult(mediaResultDTO: MediaResultDTO) : MediaResult { return MediaResult( posterPath = mediaResultDTO.posterPath, - adult = !mediaResultDTO.adult, + adult = mediaResultDTO.adult!!, overview = mediaResultDTO.overview, releaseDate = mediaResultDTO.releaseDate ?: mediaResultDTO.firstAirDate!! , originCountry = mediaResultDTO.originCountry, diff --git a/Sources/app/src/main/res/layout/fragment_movies.xml b/Sources/app/src/main/res/layout/fragment_movies.xml index a3d0e0f..7016eed 100644 --- a/Sources/app/src/main/res/layout/fragment_movies.xml +++ b/Sources/app/src/main/res/layout/fragment_movies.xml @@ -20,7 +20,7 @@ - + - + + + + + + + + android:orientation="vertical"> + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/Sources/app/src/main/res/layout/item_tv_show_category.xml b/Sources/app/src/main/res/layout/item_tv_show_category.xml new file mode 100644 index 0000000..188f2fb --- /dev/null +++ b/Sources/app/src/main/res/layout/item_tv_show_category.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/app/src/main/res/values/strings.xml b/Sources/app/src/main/res/values/strings.xml index 6280e15..79bb1d8 100644 --- a/Sources/app/src/main/res/values/strings.xml +++ b/Sources/app/src/main/res/values/strings.xml @@ -22,4 +22,11 @@ Les mieux notés + + Populaires + Diffusées aujourd\'hui + En cours de diffusion + Les mieux notées + + \ No newline at end of file