From 5a6b157c4f776860159bb6d31719783dfa59adb7 Mon Sep 17 00:00:00 2001 From: Jordan Artzet Date: Thu, 2 Feb 2023 22:48:40 +0100 Subject: [PATCH] :construction: rebuild the dtos correctly --- .../api/MovieApplicationAPI.kt | 2 +- .../api/dtos/MediaResultDTO.kt | 42 +++++++++++ .../pm/movieapplication/api/dtos/MovieDTO.kt | 58 ++++++--------- .../api/dtos/MovieResultDTO.kt | 1 - .../movieapplication/api/dtos/PopularDTO.kt | 2 +- .../pm/movieapplication/api/dtos/TvShowDTO.kt | 29 +++++++- .../pm/movieapplication/data/dao/MovieDAO.kt | 6 +- .../fr/iut/pm/movieapplication/model/Movie.kt | 64 ---------------- .../iut/pm/movieapplication/model/Popular.kt | 3 +- .../model/media/MediaResult.kt | 24 ++++++ .../model/media/movie/Movie.kt | 22 ++++++ .../model/media/movie/MovieDetails.kt | 50 +++++++++++++ .../model/media/tvshow/TvShow.kt | 20 +++++ .../model/media/tvshow/TvShowDetails.kt | 4 + .../movieapplication/network/dtos/GenreDTO.kt | 7 -- .../repository/MovieRepository.kt | 22 +++--- .../repository/TVShowRepository.kt | 4 + .../ui/adapter/HomeItemAdapter.kt | 15 +++- .../ui/adapter/MovieAdapter.kt | 59 +++++++++++++++ .../ui/fragments/HomeSectionsFragment.kt | 5 +- .../ui/fragments/MoviesFragment.kt | 74 ++++++++++++++++--- .../movieapplication/ui/viewmodel/MoviesVM.kt | 16 +--- .../pm/movieapplication/utils/Constants.kt | 6 ++ .../iut/pm/movieapplication/utils/Mapper.kt | 36 --------- .../utils/MediaResultMapper.kt | 71 ++++++++++++++++++ .../src/main/res/layout/fragment_movies.xml | 2 +- .../res/layout/item_vertical_fragment.xml | 63 ++++++++-------- 27 files changed, 482 insertions(+), 225 deletions(-) create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt delete mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Movie.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/MediaResult.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/Movie.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/MovieDetails.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShowDetails.kt delete mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/network/dtos/GenreDTO.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/MovieAdapter.kt delete mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Mapper.kt create mode 100644 Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt 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 68b255c..803183d 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 @@ -12,7 +12,7 @@ import retrofit2.http.Query interface MovieApplicationAPI { @GET("movie/popular") - fun getPopularMovies(@Query("api_key") apiKey : String = API_KEY) : Call + fun getPopularMovies(@Query("api_key") apiKey : String = API_KEY, @Query("page") page : Int = 1) : Call @GET("movie/top_rated") fun getTopRatedMovies(@Query("api_key") apiKey: String = API_KEY) : Call 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 new file mode 100644 index 0000000..b428527 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MediaResultDTO.kt @@ -0,0 +1,42 @@ +package fr.iut.pm.movieapplication.api.dtos + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@Json(name = "results") +data class MediaResultDTO( + + @Json(name = "poster_path") + val posterPath : String, + val adult : Boolean, + val overview : String, + @Json(name = "first_air_date") + val firstAirDate : String?, + @Json(name = "release_date") + val releaseDate : String?, + @Json(name = "origin_country") + val originCountry : List?, + @Json(name = "genre_ids") + val genreIds : List, + val id : Int, + @Json(name = "original_title") + val originalTitle : String?, + @Json(name = "original_language") + val originalLanguage : String, + val title : String?, + @Json(name = "backdrop_path") + val backdropPath : String, + val popularity : Double, + @Json(name = "vote_count") + val voteCount : Int, + val video : Boolean?, + @Json(name = "vote_average") + val voteAverage : Double, + val name: String?, + @Json(name = "original_name") + val originalName : String?, + @Json(name = "media_type") + val mediaType : String +) { + +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDTO.kt index 83abc57..73f4017 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDTO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDTO.kt @@ -1,44 +1,32 @@ package fr.iut.pm.movieapplication.api.dtos -import androidx.room.ColumnInfo -import androidx.room.Embedded -import androidx.room.PrimaryKey -import androidx.room.Relation import com.squareup.moshi.Json -import fr.iut.pm.movieapplication.model.Genre -import fr.iut.pm.movieapplication.model.ProductionCompany -import fr.iut.pm.movieapplication.model.ProductionCountry -import fr.iut.pm.movieapplication.network.dtos.GenreDTO -class MovieDTO ( - val adult: Boolean, - val budget: Int, - val genres: Array?, - val homepage: String?, - val id: Int, - @Json(name = "original_language") - val originalLanguage: String, - @Json(name = "original_title") - val originalTitle: String, - val overview: String?, - val popularity: Double, +open class MovieDTO ( @Json(name = "poster_path") - val posterPath: String?, - @Json(name = "production_countries") - val productionCountries: Array, + open val posterPath: String?, + open val adult: Boolean, + open val overview: String, @Json(name = "release_date") - val releaseDate: String, - val revenue: Int, - val runtime: Int?, - //var spokenLanguages : Array, - val status: String, - @Json(name = "tag_line") - val tagLine: String?, - val title: String, - @Json(name = "vote_average") - val voteAverage: Double, + open val releaseDate: String, + @Json(name = "genre_ids") + open val genreIds: List, + open val id: Int, + @Json(name = "original_title") + open val originalTitle: String, + @Json(name = "original_language") + open val originalLanguage: String, + open val title: String, + @Json(name = "backdrop_path") + open val backdropPath: String?, + open val popularity: Double, @Json(name = "vote_count") - val voteCount: Int, - val backdropPath: String? + open val voteCount: Int, + open val video : Boolean, + @Json(name = "vote_average") + open val voteAverage: Double + + ){ + } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieResultDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieResultDTO.kt index 68acf5b..bc1c340 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieResultDTO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieResultDTO.kt @@ -28,7 +28,6 @@ class MovieResultDTO( val popularity : Double?, @Json(name = "vote_count") val voteCount : Int?, - val video : Boolean?, @Json(name = "vote_average") val voteAverage : Double? diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/PopularDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/PopularDTO.kt index baf6422..2db4407 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/PopularDTO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/PopularDTO.kt @@ -9,7 +9,7 @@ class PopularDTO( @Json(name = "page") val page : Int, @Json(name = "results") - val results : List, + val results : List, @Json(name = "total_results") val totalResults : Int, @Json(name = "total_pages") diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/TvShowDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/TvShowDTO.kt index 9e83997..be4247c 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/TvShowDTO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/TvShowDTO.kt @@ -2,8 +2,29 @@ package fr.iut.pm.movieapplication.api.dtos import com.squareup.moshi.Json -data class TvShowDTO( +open class TvShowDTO( + + @Json(name = "poster_path") + open val posterPath: String?, + open val popularity: Double, + open val id: Int, @Json(name = "backdrop_path") - val backdropPath : String? -) { -} \ No newline at end of file + open val backdropPath: String?, + @Json(name = "vote_average") + open val voteAverage: Double, + open val overview: String, + @Json(name = "first_air_date") + open val firstAirDate: String, + @Json(name = "origin_country") + open val originCountry: List, + @Json(name = "genre_ids") + open val genreIds: List, + @Json(name = "original_language") + open val originalLanguage: String, + @Json(name = "vote_count") + open val voteCount: Int, + open val name: String, + @Json(name = "original_name") + open val originalName: String, + ) +{} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieDAO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieDAO.kt index cf78568..5efb718 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieDAO.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieDAO.kt @@ -4,17 +4,17 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import fr.iut.pm.movieapplication.model.Movie +import fr.iut.pm.movieapplication.model.media.movie.MovieDetails import kotlinx.coroutines.flow.Flow @Dao interface MovieDAO { @Query("SELECT * FROM movies_table ORDER BY original_title ASC") - fun getMovieByAlphabetizeMovie() : Flow> + fun getMovieByAlphabetizeMovie() : Flow> @Insert(onConflict = OnConflictStrategy.IGNORE) - suspend fun insert(movie : Movie) + suspend fun insert(movie : MovieDetails) @Query("DELETE FROM movies_table") suspend fun deleteAll() diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Movie.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Movie.kt deleted file mode 100644 index 1b8021b..0000000 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Movie.kt +++ /dev/null @@ -1,64 +0,0 @@ -package fr.iut.pm.movieapplication.model - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity(tableName = "movies_table") -data class Movie( - @ColumnInfo(name = "adult") - val adult: Boolean, - @ColumnInfo(name = "budget") - val budget: Int?, - @ColumnInfo(name = "genres") - val genres: Array?, - @ColumnInfo(name = "homepage") - val homePage: String?, - @PrimaryKey - @ColumnInfo(name = "id") - val movieId: Int, - @ColumnInfo(name = "original_language") - val originalLanguage: String?, - @ColumnInfo(name = "original_title") - val originalTitle: String?, - val overview: String?, - val popularity: Double?, - @ColumnInfo(name = "poster_path") - val posterPath: String?, - val productionCompanies: Array?, - @ColumnInfo(name = "production_countries") - val productionCountries: Array?, - @ColumnInfo(name = "release_date") - val releaseDate: String?, - val revenue: Int?, - val runtime: Int?, - //var spokenLanguages : Array, - val status: String?, - @ColumnInfo(name = "tag_line") - val tagLine: String?, - val title: String?, - @ColumnInfo(name = "vote_average") - val voteAverage: Double?, - @ColumnInfo(name = "vote_count") - val voteCount: Int?, - val backdropPath: String? - - -) { - - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Movie - - if (movieId != other.movieId) return false - - return true - } - - override fun hashCode(): Int { - return movieId - } -} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Popular.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Popular.kt index 256c611..c278e4d 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Popular.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/Popular.kt @@ -2,13 +2,14 @@ package fr.iut.pm.movieapplication.model import androidx.room.ColumnInfo import androidx.room.Embedded +import fr.iut.pm.movieapplication.model.media.movie.MovieDetails data class Popular( @ColumnInfo("page") val page : Int, @ColumnInfo("results") @Embedded - val results : List, + val results : List, val totalResults : Int, val totalPages : Int diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/MediaResult.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/MediaResult.kt new file mode 100644 index 0000000..d443566 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/MediaResult.kt @@ -0,0 +1,24 @@ +package fr.iut.pm.movieapplication.model.media + +data class MediaResult( + + val posterPath: String? = null, + val adult: Boolean, + val overview: String, + val firstAirDate: String? = null, + val releaseDate: String? = null, + val originCountry: List? = null, + val genreIds: List, + val id: Int, + val originalTitle: String? = null, + val originalLanguage: String, + val title: String?, + val backdropPath: String? = null, + val popularity: Double, + val voteCount: Int, + val voteAverage: Double, + val name: String? = null, + val originalName: String? = null, + val mediaType : String +) +{} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/Movie.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/Movie.kt new file mode 100644 index 0000000..1a5021b --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/Movie.kt @@ -0,0 +1,22 @@ +package fr.iut.pm.movieapplication.model.media.movie + +open class Movie( + open val posterPath: String?, + open val adult: Boolean, + open val overview: String, + open val releaseDate: String, + open val genreIds: List, + open val id: Int, + open val originalTitle: String, + open val originalLanguage: String, + open val title: String?, + open val backdropPath: String?, + open val popularity: Double, + open val voteCount: Int, + open val video: Boolean?, + open val voteAverage: Double, +) +{ + + +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/MovieDetails.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/MovieDetails.kt new file mode 100644 index 0000000..c70e337 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/movie/MovieDetails.kt @@ -0,0 +1,50 @@ +package fr.iut.pm.movieapplication.model.media.movie + +import fr.iut.pm.movieapplication.model.ProductionCompany +import fr.iut.pm.movieapplication.model.ProductionCountry + + +data class MovieDetails( + + override val posterPath: String, + override val adult: Boolean, + override val overview: String, + override val releaseDate: String, + override val genreIds : List, + override val id: Int, + override val originalTitle: String, + override val originalLanguage: String, + override val title: String?, + override val backdropPath: String?, + override val popularity: Double, + override val voteCount: Int, + override val video: Boolean?, + override val voteAverage: Double, + val mediaType: String, + + val budget: Int?, + val homePage: String?, + val productionCompanies: Array?, + val productionCountries: Array?, + val revenue: Int?, + val runtime: Int?, + val status: String?, + val tagLine: String? + +) : Movie(posterPath, + adult, + overview, + releaseDate, + genreIds, + id, + originalTitle, + originalLanguage, + title, + backdropPath, + popularity, + voteCount, + video, + voteAverage) { + + +} \ No newline at end of file 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 new file mode 100644 index 0000000..b9ac31a --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShow.kt @@ -0,0 +1,20 @@ +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", +) +{ +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShowDetails.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShowDetails.kt new file mode 100644 index 0000000..7a96534 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/model/media/tvshow/TvShowDetails.kt @@ -0,0 +1,4 @@ +package fr.iut.pm.movieapplication.model.media.tvshow + +class TvShowDetails { +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/network/dtos/GenreDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/network/dtos/GenreDTO.kt deleted file mode 100644 index 5405548..0000000 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/network/dtos/GenreDTO.kt +++ /dev/null @@ -1,7 +0,0 @@ -package fr.iut.pm.movieapplication.network.dtos - -data class GenreDTO( - private val id : Int, - private val name : String -) { -} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieRepository.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieRepository.kt index c099d8e..8212a01 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieRepository.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieRepository.kt @@ -3,20 +3,20 @@ 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.Movie -import fr.iut.pm.movieapplication.utils.Constants.Companion.API_KEY -import fr.iut.pm.movieapplication.utils.Mapper +import fr.iut.pm.movieapplication.model.media.MediaResult +import fr.iut.pm.movieapplication.model.media.movie.Movie +import fr.iut.pm.movieapplication.utils.MediaResultMapper import retrofit2.Call import retrofit2.Callback import retrofit2.Response class MovieRepository() { - fun getPopularMovies(callback: (List) -> Unit ) { + fun getPopularMovies(page : Int = 1 ,callback: (List) -> Unit ) { val listMovie : MutableList = mutableListOf() - RetrofitInstance.api.getPopularMovies().enqueue(object : + RetrofitInstance.api.getPopularMovies(page = page).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { @@ -25,9 +25,9 @@ class MovieRepository() { val listMoviesDTO = popularDTO?.results listMoviesDTO?.forEach { - val movie = Mapper.MapToMovie(it) + val movie = MediaResultMapper.mapToMovie(it) listMovie.add(movie) - Log.d("Movie ", movie.title!!) + Log.d("Movie ", movie.title!! ) } } @@ -41,8 +41,8 @@ class MovieRepository() { }) } - fun getTrends(callback: (List) -> Unit) { - val listMovie : MutableList = mutableListOf() + fun getTrends(callback: (List) -> Unit) { + val listMovie : MutableList = mutableListOf() RetrofitInstance.api.getTrending().enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { @@ -50,7 +50,7 @@ class MovieRepository() { Log.d("Response",response.body().toString()) val popularDTO = response.body() popularDTO?.results?.forEach { - val movie = Mapper.MapToMovie(it) + val movie = MediaResultMapper.mapToMediaResult(it) listMovie.add(movie) movie.title?.let { it1 -> Log.d("Movie", it1) } } @@ -59,7 +59,7 @@ class MovieRepository() { } override fun onFailure(call: Call, t: Throwable) { - Log.d("Error failure", t.message.toString()) + Log.d("Error failure", t.printStackTrace().toString()) } }) } 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..b19f419 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/TVShowRepository.kt @@ -0,0 +1,4 @@ +package fr.iut.pm.movieapplication.repository + +class TVShowRepository { +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/HomeItemAdapter.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/HomeItemAdapter.kt index 20acfe9..bb5a305 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/HomeItemAdapter.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/HomeItemAdapter.kt @@ -11,14 +11,17 @@ import androidx.recyclerview.widget.RecyclerView import coil.load import fr.iut.pm.movieapplication.R import fr.iut.pm.movieapplication.api.config.GlobalImageConfig -import fr.iut.pm.movieapplication.model.Movie +import fr.iut.pm.movieapplication.model.media.MediaResult +import fr.iut.pm.movieapplication.model.media.movie.Movie +import fr.iut.pm.movieapplication.model.media.movie.MovieDetails +import fr.iut.pm.movieapplication.model.media.tvshow.TvShow import fr.iut.pm.movieapplication.ui.activity.MainActivity import fr.iut.pm.movieapplication.utils.Constants.Companion.IMG_URL class HomeItemAdapter( private val context: MainActivity, private val layoutId: Int, - private val list: List + private val list: List ) : RecyclerView.Adapter() { class ViewHolder(view : View) : RecyclerView.ViewHolder(view) { @@ -39,13 +42,19 @@ class HomeItemAdapter( Log.d("SINGLETON", GlobalImageConfig.baseUrl) val imgUri = currentItem.posterPath?.let { (IMG_URL + it).toUri().buildUpon().scheme("https").build() - } Log.d("SINGLETON", imgUri.toString() ) holder.itemImage.load(imgUri) holder.itemName.text = currentItem.title holder.itemDate.text = currentItem.releaseDate + holder.itemView.setOnClickListener { + onItemClick(currentItem) + } + + } + private fun onItemClick(item : MediaResult) { + Log.d("item clicked", item.toString()) } override fun getItemCount(): Int = list.size 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 new file mode 100644 index 0000000..dc28e98 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/adapter/MovieAdapter.kt @@ -0,0 +1,59 @@ +package fr.iut.pm.movieapplication.ui.adapter + +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.core.net.toUri +import androidx.recyclerview.widget.RecyclerView +import coil.load +import fr.iut.pm.movieapplication.R +import fr.iut.pm.movieapplication.api.config.GlobalImageConfig +import fr.iut.pm.movieapplication.model.media.movie.Movie +import fr.iut.pm.movieapplication.ui.activity.MainActivity +import fr.iut.pm.movieapplication.utils.Constants + +class MovieAdapter( + private val context: MainActivity, + private val layoutId: Int, + private val list: List +) : RecyclerView.Adapter(){ + + class ViewHolder(view : View) : RecyclerView.ViewHolder(view) { + val itemImage: ImageView = view.findViewById(R.id.item_image) + val itemName: TextView = view.findViewById(R.id.item_name) + val itemDate: TextView = view.findViewById(R.id.item_date) + } + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeItemAdapter.ViewHolder { + val view = LayoutInflater + .from(parent.context) + .inflate(layoutId, parent, false) + return HomeItemAdapter.ViewHolder(view) + } + + override fun getItemCount(): Int = list.size + + + override fun onBindViewHolder(holder: HomeItemAdapter.ViewHolder, position: Int) { + val currentItem = list[position] + Log.d("SINGLETON", GlobalImageConfig.baseUrl) + val imgUri = currentItem.posterPath?.let { + (Constants.IMG_URL + it).toUri().buildUpon().scheme("https").build() + } + Log.d("SINGLETON", imgUri.toString() ) + holder.itemImage.load(imgUri) + holder.itemName.text = currentItem.title + holder.itemDate.text = currentItem.releaseDate + holder.itemView.setOnClickListener { + onItemClick(currentItem) + } + } + + private fun onItemClick(item : Movie) { + Log.d("item clicked", item.toString()) + } +} \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/HomeSectionsFragment.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/HomeSectionsFragment.kt index d321a90..528981f 100644 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/HomeSectionsFragment.kt +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/HomeSectionsFragment.kt @@ -7,11 +7,10 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.recyclerview.widget.RecyclerView import fr.iut.pm.movieapplication.R -import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO -import fr.iut.pm.movieapplication.model.Movie import fr.iut.pm.movieapplication.ui.activity.MainActivity import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter import fr.iut.pm.movieapplication.ui.adapter.HomeItemDecoration +import fr.iut.pm.movieapplication.ui.adapter.MovieAdapter import fr.iut.pm.movieapplication.ui.viewmodel.HomeSectionsVM class HomeSectionsFragment( @@ -33,7 +32,7 @@ class HomeSectionsFragment( //get the popularity RecyclerView context.movieRepository.getPopularMovies { val homePopularityRecyclerView = view?.findViewById(R.id.home_popularity_recycler_view) - homePopularityRecyclerView?.adapter = HomeItemAdapter(context,R.layout.item_horizontal_home_page,it) + homePopularityRecyclerView?.adapter = MovieAdapter(context,R.layout.item_horizontal_home_page,it) homePopularityRecyclerView?.addItemDecoration(HomeItemDecoration()) } //get the free RecyclerView 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 3623498..9c868c9 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 @@ -6,37 +6,89 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import fr.iut.pm.movieapplication.R -import fr.iut.pm.movieapplication.api.RetrofitInstance -import fr.iut.pm.movieapplication.model.Movie +import fr.iut.pm.movieapplication.model.media.MediaResult +import fr.iut.pm.movieapplication.model.media.movie.Movie +import fr.iut.pm.movieapplication.model.media.movie.MovieDetails import fr.iut.pm.movieapplication.repository.MovieRepository import fr.iut.pm.movieapplication.ui.activity.MainActivity -import fr.iut.pm.movieapplication.ui.adapter.CategoryItemDecoration import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter +import fr.iut.pm.movieapplication.ui.adapter.MovieAdapter import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVM import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVMFactory -import fr.iut.pm.movieapplication.ui.viewmodel.viewModelFactory -import kotlinx.coroutines.launch +import fr.iut.pm.movieapplication.utils.Constants.Companion.PAGE_SIZE class MoviesFragment( private val context : MainActivity ) : Fragment() { + private var isLoading = false + private var isLastPage = false + private var currentPage = 1 + private var currentList : MutableList = mutableListOf() + private val moviesVM: MoviesVM by viewModels{ MoviesVMFactory(repository = MovieRepository())} + lateinit var moviesRecyclerView : RecyclerView override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_movies, container, false) + // Get the RecyclerView + moviesRecyclerView = view.findViewById(R.id.movies_item_recycler_view) + + // Initialized the data inside our RecyclerView context.movieRepository.getPopularMovies { listMovies -> - val moviesRecyclerView = view?.findViewById(R.id.movies_item_recycler_view) - moviesRecyclerView?.adapter = HomeItemAdapter(context, R.layout.item_vertical_fragment, listMovies) - moviesRecyclerView ?. layoutManager = GridLayoutManager (context, 2) - moviesRecyclerView?.addItemDecoration(CategoryItemDecoration()) + currentList.addAll(0,listMovies) + moviesRecyclerView.adapter = MovieAdapter(context, R.layout.item_vertical_fragment, currentList) + moviesRecyclerView.layoutManager = GridLayoutManager (context, 3) + } + + // Create the ScrollListener + val scrollListener = object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + val layoutManager = moviesRecyclerView.layoutManager as GridLayoutManager + val visibleItemCount = layoutManager.childCount + val totalItemCount = layoutManager.itemCount + val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition() + + // If we are not already loading data and it's not the last page + if(!isLoading && !isLastPage) { + if(visibleItemCount + firstVisibleItemPosition >= totalItemCount + && firstVisibleItemPosition >= 0 + && totalItemCount >= PAGE_SIZE + ) { + loadMoreMovies() + } + } + } } + // Add the ScrollLister created before to our RecyclerView + moviesRecyclerView.addOnScrollListener(scrollListener) + return view } + + /** + * Method to load data when the user reaches the bottom of the view + */ + private fun loadMoreMovies() { + isLoading = true + currentPage += 1 + + if(currentPage == 1000) isLastPage = true + + val start = currentList.size + context.movieRepository.getPopularMovies(currentPage) { listMovies -> + + currentList.addAll(start, listMovies) + moviesRecyclerView.adapter?.notifyItemRangeChanged(start, listMovies.size) + + } + + isLoading = false + } } \ 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 67fb70d..8548868 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 @@ -1,28 +1,18 @@ package fr.iut.pm.movieapplication.ui.viewmodel import androidx.lifecycle.* -import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO -import fr.iut.pm.movieapplication.model.Movie +import fr.iut.pm.movieapplication.model.media.movie.MovieDetails import fr.iut.pm.movieapplication.repository.MovieRepository -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch class MoviesVM(private val repository: MovieRepository) : ViewModel() { - private val _popularMovies = MutableLiveData>() - val popularMovies : LiveData> = _popularMovies + private val _popularMovies = MutableLiveData>() + val popularMovies : LiveData> = _popularMovies init { //loadData() } - suspend fun loadData() { - viewModelScope.launch { - repository.getPopularMovies { movies -> - _popularMovies.value = movies - } - }.join() - - } } 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 4081cf5..3bc70c1 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 @@ -3,8 +3,14 @@ package fr.iut.pm.movieapplication.utils class Constants { companion object { + + //API const val BASE_URL = "https://api.themoviedb.org/3/" const val IMG_URL = "https://image.tmdb.org/t/p/w500" const val API_KEY = "8f14a279249638d7f247d0d7298b21b4" + + + //VIEW PAGINATION + const val PAGE_SIZE = 20 } } \ No newline at end of file diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Mapper.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Mapper.kt deleted file mode 100644 index 9c91be0..0000000 --- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/Mapper.kt +++ /dev/null @@ -1,36 +0,0 @@ -package fr.iut.pm.movieapplication.utils - -import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO -import fr.iut.pm.movieapplication.model.Movie - -object Mapper { - - fun MapToMovie( movieDTO : MovieResultDTO) : Movie { - return Movie( - adult = movieDTO.adult, - posterPath = movieDTO.posterPath, - overview = movieDTO.overview, - releaseDate = movieDTO.releaseDate, - movieId = movieDTO.id, - originalTitle = movieDTO.originalTitle, - originalLanguage = movieDTO.originalLanguage, - title = movieDTO.title, - backdropPath = movieDTO.backdropPath, - popularity = movieDTO.popularity, - voteCount = movieDTO.voteCount, - voteAverage = movieDTO.voteAverage, - budget = null, - genres = null, - homePage = null, - productionCompanies = null, - productionCountries = null, - revenue = null, - runtime = null, - status = null, - tagLine = null - - ) - } - - -} \ 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 new file mode 100644 index 0000000..3b3bca8 --- /dev/null +++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/utils/MediaResultMapper.kt @@ -0,0 +1,71 @@ +package fr.iut.pm.movieapplication.utils + +import fr.iut.pm.movieapplication.api.dtos.MediaResultDTO +import fr.iut.pm.movieapplication.model.media.MediaResult +import fr.iut.pm.movieapplication.model.media.movie.Movie +import fr.iut.pm.movieapplication.model.media.tvshow.TvShow + +object MediaResultMapper { + + fun mapToTvShow(mediaResultDTO: MediaResultDTO): TvShow { + return TvShow( + posterPath = mediaResultDTO.posterPath, + popularity = mediaResultDTO.popularity, + id = mediaResultDTO.id, + backdropPath = mediaResultDTO.backdropPath!!, + voteAverage = mediaResultDTO.voteAverage, + overview = mediaResultDTO.overview, + firstAirDate = mediaResultDTO.firstAirDate, + originCountry = mediaResultDTO.originCountry!!, + genreIds = mediaResultDTO.genreIds, + originalLanguage = mediaResultDTO.originalLanguage, + voteCount = mediaResultDTO.voteCount, + name = mediaResultDTO.name!!, + originalName = mediaResultDTO.originalName!! + ) + } + + fun mapToMovie(mediaResultDTO: MediaResultDTO): Movie { + return Movie( + posterPath = mediaResultDTO.posterPath, + adult = mediaResultDTO.adult == false, + overview = mediaResultDTO.overview, + releaseDate = mediaResultDTO.releaseDate!!, + genreIds = mediaResultDTO.genreIds, + id = mediaResultDTO.id, + originalTitle = mediaResultDTO.originalTitle!!, + originalLanguage = mediaResultDTO.originalLanguage, + title = mediaResultDTO.title, + backdropPath = mediaResultDTO.backdropPath, + popularity = mediaResultDTO.popularity, + voteCount = mediaResultDTO.voteCount, + video = mediaResultDTO.video, + voteAverage = mediaResultDTO.voteAverage + ) + } + + fun mapToMediaResult(mediaResultDTO: MediaResultDTO) : MediaResult { + return MediaResult( + posterPath = mediaResultDTO.posterPath, + adult = mediaResultDTO.adult == false, + overview = mediaResultDTO.overview, + firstAirDate = mediaResultDTO.firstAirDate, + releaseDate = mediaResultDTO.releaseDate, + originCountry = mediaResultDTO.originCountry, + genreIds = mediaResultDTO.genreIds, + id = mediaResultDTO.id, + originalTitle = mediaResultDTO.originalTitle, + originalLanguage = mediaResultDTO.originalLanguage, + title = mediaResultDTO.title, + backdropPath = mediaResultDTO.backdropPath, + popularity = mediaResultDTO.popularity, + voteCount = mediaResultDTO.voteCount, + voteAverage = mediaResultDTO.voteAverage, + name = mediaResultDTO.name, + originalName = mediaResultDTO.originalName, + mediaType = mediaResultDTO.mediaType + ) + } + + +} \ No newline at end of file diff --git a/Sources/app/src/main/res/layout/fragment_movies.xml b/Sources/app/src/main/res/layout/fragment_movies.xml index 4094d47..bda7cfc 100644 --- a/Sources/app/src/main/res/layout/fragment_movies.xml +++ b/Sources/app/src/main/res/layout/fragment_movies.xml @@ -7,7 +7,7 @@ diff --git a/Sources/app/src/main/res/layout/item_vertical_fragment.xml b/Sources/app/src/main/res/layout/item_vertical_fragment.xml index 6c2d62a..ef3a88c 100644 --- a/Sources/app/src/main/res/layout/item_vertical_fragment.xml +++ b/Sources/app/src/main/res/layout/item_vertical_fragment.xml @@ -1,46 +1,49 @@ + android:layout_height="match_parent" + android:layout_marginStart="4dp" + android:layout_marginLeft="4dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="4dp" + android:layout_marginRight="4dp" + android:layout_marginBottom="8dp" + app:cardCornerRadius="10dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - - - - - + + + + +