diff --git a/Sources/app/build.gradle b/Sources/app/build.gradle
index cd5b0a7..d8696c7 100644
--- a/Sources/app/build.gradle
+++ b/Sources/app/build.gradle
@@ -45,14 +45,15 @@ dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
- implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
-
implementation "androidx.fragment:fragment-ktx:1.5.5"
+ implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
+ implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
+ implementation "com.google.android.material:material:$rootProject.materialVersion"
// Room components
+ implementation "androidx.room:room-runtime:$rootProject.roomVersion"
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
- androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
@@ -68,17 +69,14 @@ dependencies {
implementation "io.coil-kt:coil:1.1.1"
// UI
- implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
- implementation "com.google.android.material:material:$rootProject.materialVersion"
+
// Moshi
implementation "com.squareup.moshi:moshi-kotlin:1.13.0"
- // Retrofit
+ // Retrofit & Moshi
implementation "com.squareup.retrofit2:retrofit:2.9.0"
- // Retrofit with Scalar Converter
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
- // Retrofit with Moshi Converter
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
// Testing
diff --git a/Sources/app/src/main/AndroidManifest.xml b/Sources/app/src/main/AndroidManifest.xml
index be3f5d0..6d1f5dd 100644
--- a/Sources/app/src/main/AndroidManifest.xml
+++ b/Sources/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
+ tools:targetApi="33">
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/MovieApplication.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/MovieApplication.kt
new file mode 100644
index 0000000..9e750db
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/MovieApplication.kt
@@ -0,0 +1,12 @@
+package fr.iut.pm.movieapplication
+
+import android.app.Application
+import androidx.room.Room
+import fr.iut.pm.movieapplication.data.database.MovieDataBase
+
+class MovieApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ MovieDataBase.initialize(this)
+ }
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDetailsDTO.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDetailsDTO.kt
index 99dfb48..248dbab 100644
--- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDetailsDTO.kt
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/api/dtos/MovieDetailsDTO.kt
@@ -24,7 +24,7 @@ data class MovieDetailsDTO(
//prod countries
@Json(name = "release_date")
val releaseDate: String,
- val revenue: Int,
+ val revenue: Long,
//spoken language
val status: String,
val title: String,
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 5efb718..81525c7 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
@@ -1,23 +1,51 @@
package fr.iut.pm.movieapplication.data.dao
-import androidx.room.Dao
-import androidx.room.Insert
-import androidx.room.OnConflictStrategy
-import androidx.room.Query
+import androidx.room.*
+import fr.iut.pm.movieapplication.data.entities.*
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>
-
@Insert(onConflict = OnConflictStrategy.IGNORE)
- suspend fun insert(movie : MovieDetails)
+ suspend fun insert(movieEntity : MovieEntity)
+
+ @Query("SELECT * FROM movies_table")
+ suspend fun getAllMovies() : List
+
+ @Query("SELECT * FROM movies_details_table")
+ suspend fun getAllMoviesDetails() : List
+
+ @Query("SELECT * FROM movies_table WHERE id = :id")
+ fun getMovieById(id : Int) : MovieEntity
+
+ //delete a movie
+ @Query("DELETE FROM movies_table WHERE id = :id")
+ suspend fun deleteMovieById(id : Int)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertMovieDetails(movieDetailsEntity: MovieDetailsEntity)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertGenres(genres : List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertMovieDetailsGenres(movieDetailsGenresEntity : List)
+
+ @Transaction
+ suspend fun insertMovieDetailsWithGenres(movieDetailsWithGenres : MovieDetailsWithGenres) {
+ insertMovieDetails(movieDetailsWithGenres.movieDetails)
+ insertGenres(movieDetailsWithGenres.genres)
+ val movieDetailsGenres = movieDetailsWithGenres.genres.map {
+ MovieDetailsGenreEntity(movieDetailsWithGenres.movieDetails.movieId, it.genreId)
+ }
+ insertMovieDetailsGenres(movieDetailsGenres)
+ }
- @Query("DELETE FROM movies_table")
- suspend fun deleteAll()
+ @Transaction
+ @Query("SELECT * FROM movies_details_table WHERE movie_id = :movieId")
+ suspend fun getMovieDetailsWithGenresById(movieId: Int): MovieDetailsWithGenres
}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieEntity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieEntity.kt
deleted file mode 100644
index c0eaec1..0000000
--- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/dao/MovieEntity.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package fr.iut.pm.movieapplication.data.dao
-
-import androidx.room.Entity
-
-@Entity("movies_table")
-class MovieEntity {
-
-
-}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/database/MovieDataBase.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/database/MovieDataBase.kt
new file mode 100644
index 0000000..5e8aaa2
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/database/MovieDataBase.kt
@@ -0,0 +1,60 @@
+package fr.iut.pm.movieapplication.data.database
+
+import android.app.Application
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import fr.iut.pm.movieapplication.MovieApplication
+import fr.iut.pm.movieapplication.data.dao.MovieDAO
+import fr.iut.pm.movieapplication.data.entities.GenreEntity
+import fr.iut.pm.movieapplication.data.entities.MovieDetailsEntity
+import fr.iut.pm.movieapplication.data.entities.MovieDetailsGenreEntity
+import fr.iut.pm.movieapplication.data.entities.MovieEntity
+
+
+const val MOVIE_DB_NAME = "movies.db"
+
+@Database( entities = [MovieEntity::class, MovieDetailsEntity::class, GenreEntity::class, MovieDetailsGenreEntity::class], version = 3)
+abstract class MovieDataBase : RoomDatabase()
+{
+ abstract fun movieDAO() : MovieDAO
+
+ companion object
+ {
+ private lateinit var application : Application
+
+ @Volatile
+ private var instance : MovieDataBase? = null
+
+ fun getInstance() : MovieDataBase
+ {
+ if (::application.isInitialized) {
+ if (instance == null)
+ synchronized(this)
+ {
+ if (instance == null)
+ instance = Room.databaseBuilder(
+ application.applicationContext,
+ MovieDataBase::class.java,
+ MOVIE_DB_NAME
+ )
+ .fallbackToDestructiveMigration()
+ .build()
+ }
+ return instance!!
+ }
+ else
+ throw RuntimeException("the database must be first initialized")
+ }
+
+ @Synchronized
+ fun initialize(app : MovieApplication)
+ {
+ if (::application.isInitialized)
+ throw RuntimeException("the database must not be initialized twice")
+
+ application = app
+ }
+ }
+}
+
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/GenreEntity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/GenreEntity.kt
new file mode 100644
index 0000000..e6b9788
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/GenreEntity.kt
@@ -0,0 +1,12 @@
+package fr.iut.pm.movieapplication.data.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "genres_table")
+data class GenreEntity(
+ @PrimaryKey @ColumnInfo("genre_id") val genreId : Int,
+ val name : String
+) {
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsEntity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsEntity.kt
new file mode 100644
index 0000000..269c273
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsEntity.kt
@@ -0,0 +1,19 @@
+package fr.iut.pm.movieapplication.data.entities
+
+import androidx.room.*
+import fr.iut.pm.movieapplication.model.Genre
+
+
+@Entity(tableName = "movies_details_table")
+data class MovieDetailsEntity(
+ @PrimaryKey @ColumnInfo("movie_id") val movieId : Int,
+ @Embedded val movie : MovieEntity,
+ val budget : Int,
+ val homepage : String?,
+ val revenue : Long,
+ val status : String
+ //Future attributes to add
+) {
+
+
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsGenreEntity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsGenreEntity.kt
new file mode 100644
index 0000000..538f94c
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsGenreEntity.kt
@@ -0,0 +1,17 @@
+package fr.iut.pm.movieapplication.data.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+
+@Entity(tableName = "movie_details_genre",
+ primaryKeys = ["movie_id", "genre_id"],
+ foreignKeys = [
+ ForeignKey(entity = MovieDetailsEntity::class, parentColumns = ["movie_id"], childColumns = ["movie_id"]),
+ ForeignKey(entity = GenreEntity::class, parentColumns = ["genre_id"], childColumns = ["genre_id"])
+ ]
+)
+data class MovieDetailsGenreEntity(
+ @ColumnInfo("movie_id") val movieId : Int,
+ @ColumnInfo("genre_id") val genreId : Int
+)
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsWithGenres.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsWithGenres.kt
new file mode 100644
index 0000000..cf15e8e
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieDetailsWithGenres.kt
@@ -0,0 +1,15 @@
+package fr.iut.pm.movieapplication.data.entities
+
+import androidx.room.Embedded
+import androidx.room.Junction
+import androidx.room.Relation
+
+data class MovieDetailsWithGenres(
+ @Embedded val movieDetails: MovieDetailsEntity,
+ @Relation(
+ parentColumn = "movie_id",
+ entityColumn = "genre_id",
+ associateBy = Junction(MovieDetailsGenreEntity::class)
+ )
+ val genres: List
+)
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieEntity.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieEntity.kt
new file mode 100644
index 0000000..217bd5a
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/entities/MovieEntity.kt
@@ -0,0 +1,23 @@
+package fr.iut.pm.movieapplication.data.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "movies_table")
+data class MovieEntity(
+ @PrimaryKey val id: Int,
+ val title: String,
+ val overview: String?,
+ @ColumnInfo("poster_path") val posterPath: String?,
+ @ColumnInfo("backdrop_path") val backdropPath: String?,
+ @ColumnInfo("release_date") val releaseDate: String,
+ @ColumnInfo("vote_average") val voteAverage: Double,
+ @ColumnInfo("vote_count") val voteCount: Int,
+ val popularity: Double,
+ @ColumnInfo("original_language") val originalLanguage: String,
+ @ColumnInfo("original_title") val originalTitle: String,
+ val adult: Boolean,
+ @ColumnInfo("is_favorite") val isFavorite: Boolean
+) {
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/GenreLocalMapper.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/GenreLocalMapper.kt
new file mode 100644
index 0000000..64355b1
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/GenreLocalMapper.kt
@@ -0,0 +1,25 @@
+package fr.iut.pm.movieapplication.data.mapper
+
+import fr.iut.pm.movieapplication.data.entities.GenreEntity
+import fr.iut.pm.movieapplication.model.Genre
+
+object GenreLocalMapper {
+
+ fun mapToGenreEntity(genre : Genre) : GenreEntity {
+ return GenreEntity(
+ genreId = genre.id,
+ name = genre.name
+ )
+ }
+
+ fun mapToGenreEntities(genres : List) : List {
+ return genres.map { mapToGenreEntity(it) }
+ }
+
+ fun mapToGenre(genreEntity : GenreEntity) : Genre {
+ return Genre(
+ id = genreEntity.genreId,
+ name = genreEntity.name
+ )
+ }
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/MovieLocalMapper.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/MovieLocalMapper.kt
new file mode 100644
index 0000000..fdd5d9a
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/data/mapper/MovieLocalMapper.kt
@@ -0,0 +1,87 @@
+package fr.iut.pm.movieapplication.data.mapper
+
+import fr.iut.pm.movieapplication.data.entities.MovieDetailsEntity
+import fr.iut.pm.movieapplication.data.entities.MovieDetailsWithGenres
+import fr.iut.pm.movieapplication.data.entities.MovieEntity
+import fr.iut.pm.movieapplication.model.media.movie.Movie
+import fr.iut.pm.movieapplication.model.media.movie.MovieDetails
+
+object MovieLocalMapper {
+
+ fun mapToMovie(movieEntity : MovieEntity) : Movie {
+ return Movie(
+ posterPath = movieEntity.posterPath,
+ adult = movieEntity.adult,
+ overview = movieEntity.overview,
+ releaseDate = movieEntity.releaseDate,
+ id = movieEntity.id,
+ originalTitle = movieEntity.originalTitle,
+ originalLanguage = movieEntity.originalLanguage,
+ title = movieEntity.title,
+ backdropPath = movieEntity.backdropPath,
+ popularity = movieEntity.popularity,
+ voteCount = movieEntity.voteCount,
+ voteAverage = movieEntity.voteAverage
+ )
+ }
+
+
+
+ fun mapToMovieEntity(movie : Movie) : MovieEntity {
+ return MovieEntity(
+ posterPath = movie.posterPath,
+ adult = movie.adult!!,
+ overview = movie.overview,
+ releaseDate = movie.releaseDate!!,
+ id = movie.id,
+ originalTitle = movie.originalTitle,
+ originalLanguage = movie.originalLanguage,
+ title = movie.title,
+ backdropPath = movie.backdropPath ,
+ popularity = movie.popularity,
+ voteCount = movie.voteCount,
+ voteAverage = movie.voteAverage,
+ isFavorite = false
+ )
+ }
+
+ fun mapToMovieDetailsEntity(movieDetails : MovieDetails) : MovieDetailsEntity {
+ return MovieDetailsEntity(
+ movieId = movieDetails.id,
+ movie = mapToMovieEntity(movieDetails),
+ budget = movieDetails.budget,
+ homepage = movieDetails.homepage,
+ revenue = movieDetails.revenue,
+ status = movieDetails.status
+ )
+ }
+
+ fun mapToMovieDetailsWithGenres(movieDetails: MovieDetails) : MovieDetailsWithGenres {
+ return MovieDetailsWithGenres(
+ movieDetails = mapToMovieDetailsEntity(movieDetails),
+ genres = movieDetails.genres.map { GenreLocalMapper.mapToGenreEntity(it) }
+ )
+ }
+
+ fun mapToMovieDetails(movieDetailsWithGenres: MovieDetailsWithGenres) : MovieDetails {
+ return MovieDetails(
+ id = movieDetailsWithGenres.movieDetails.movieId,
+ posterPath = movieDetailsWithGenres.movieDetails.movie.posterPath,
+ adult = movieDetailsWithGenres.movieDetails.movie.adult,
+ overview = movieDetailsWithGenres.movieDetails.movie.overview,
+ releaseDate = movieDetailsWithGenres.movieDetails.movie.releaseDate,
+ originalTitle = movieDetailsWithGenres.movieDetails.movie.originalTitle,
+ originalLanguage = movieDetailsWithGenres.movieDetails.movie.originalLanguage,
+ title = movieDetailsWithGenres.movieDetails.movie.title,
+ backdropPath = movieDetailsWithGenres.movieDetails.movie.backdropPath,
+ popularity = movieDetailsWithGenres.movieDetails.movie.popularity,
+ voteCount = movieDetailsWithGenres.movieDetails.movie.voteCount,
+ voteAverage = movieDetailsWithGenres.movieDetails.movie.voteAverage,
+ budget = movieDetailsWithGenres.movieDetails.budget,
+ homepage = movieDetailsWithGenres.movieDetails.homepage,
+ revenue = movieDetailsWithGenres.movieDetails.revenue,
+ status = movieDetailsWithGenres.movieDetails.status,
+ genres = movieDetailsWithGenres.genres.map { GenreLocalMapper.mapToGenre(it) }
+ )
+ }
+}
\ 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
index a9c63d9..7bb297f 100644
--- 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
@@ -19,7 +19,7 @@ class MovieDetails(
//prod companies
//prod countries
releaseDate : String?,
- val revenue : Int,
+ val revenue : Long,
//spoken language
val status : String,
title : String,
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/MovieAPIRepository.kt
similarity index 97%
rename from Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieRepository.kt
rename to Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/MovieAPIRepository.kt
index a42cbd3..2ca77aa 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/MovieAPIRepository.kt
@@ -2,7 +2,6 @@ package fr.iut.pm.movieapplication.repository
import android.util.Log
import fr.iut.pm.movieapplication.api.RetrofitInstance
-import fr.iut.pm.movieapplication.api.dtos.MovieDetailsDTO
import fr.iut.pm.movieapplication.model.media.movie.Movie
import fr.iut.pm.movieapplication.model.media.movie.MovieDetails
import fr.iut.pm.movieapplication.utils.MediaResultMapper
@@ -10,7 +9,7 @@ import fr.iut.pm.movieapplication.utils.MovieMapper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
-class MovieRepository {
+class MovieAPIRepository {
suspend fun getPopularMovies(page : Int = 1) : List = withContext(Dispatchers.IO)
{
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/PopularRepository.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/PopularRepository.kt
deleted file mode 100644
index 6c8a645..0000000
--- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/PopularRepository.kt
+++ /dev/null
@@ -1,16 +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.utils.Constants.Companion.API_KEY
-import retrofit2.Call
-import retrofit2.Callback
-import retrofit2.Response
-
-class PopularRepository() {
-
- suspend fun getPopular(): PopularDTO? {
- throw NoSuchMethodError()
- }
-}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/local/MovieLocalRepository.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/local/MovieLocalRepository.kt
new file mode 100644
index 0000000..e6c5cbb
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/repository/local/MovieLocalRepository.kt
@@ -0,0 +1,36 @@
+package fr.iut.pm.movieapplication.repository.local
+
+import android.util.Log
+import fr.iut.pm.movieapplication.data.dao.MovieDAO
+import fr.iut.pm.movieapplication.data.mapper.MovieLocalMapper
+import fr.iut.pm.movieapplication.model.media.movie.Movie
+import fr.iut.pm.movieapplication.model.media.movie.MovieDetails
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+class MovieLocalRepository(private val movieDAO: MovieDAO) {
+
+ suspend fun insertMovie(movie : Movie) = withContext(Dispatchers.IO) {
+ movieDAO.insert(MovieLocalMapper.mapToMovieEntity(movie))
+ }
+
+ suspend fun insertMovieDetails(movieDetails : MovieDetails) = withContext(Dispatchers.IO) {
+ Log.i("MovieLocalRepository", "INSERT MOVIE DETAILS")
+ movieDAO.insertMovieDetailsWithGenres(MovieLocalMapper.mapToMovieDetailsWithGenres(movieDetails))
+ }
+
+ suspend fun getMovieDetailsById(id : Int) : MovieDetails {
+ return MovieLocalMapper.mapToMovieDetails(movieDAO.getMovieDetailsWithGenresById(id))
+ }
+
+ suspend fun getAllMovies() : List = withContext(Dispatchers.IO) {
+ val listMovie : MutableList = mutableListOf()
+ val listMoviesEntities = movieDAO.getAllMoviesDetails()
+
+ listMoviesEntities.forEach { movieEntity ->
+ listMovie.add(MovieLocalMapper.mapToMovie(movieEntity.movie))
+ }
+
+ 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 d741285..426b00b 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
@@ -1,16 +1,13 @@
package fr.iut.pm.movieapplication.ui.activity
-import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
-import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView
import fr.iut.pm.movieapplication.R
-import fr.iut.pm.movieapplication.repository.MediaRepository
-import fr.iut.pm.movieapplication.repository.MovieRepository
+import fr.iut.pm.movieapplication.ui.fragments.FavoritesFragment
import fr.iut.pm.movieapplication.ui.fragments.HomeSectionsFragment
import fr.iut.pm.movieapplication.ui.fragments.MoviesFragment
import fr.iut.pm.movieapplication.ui.fragments.TvShowsFragment
@@ -41,6 +38,10 @@ class MainActivity : AppCompatActivity() {
loadFragments(TvShowsFragment())
return@setOnItemSelectedListener true
}
+ R.id.favorites_page -> {
+ loadFragments(FavoritesFragment())
+ return@setOnItemSelectedListener true
+ }
else -> false
}
}
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/dialog/MovieDialog.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/dialog/MovieDialog.kt
index 5847821..ea5f0b1 100644
--- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/dialog/MovieDialog.kt
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/dialog/MovieDialog.kt
@@ -31,6 +31,11 @@ class MovieDialog : DialogFragment() {
(Constants.IMG_URL + it).toUri().buildUpon().scheme("https").build()
})
}
+
+ binding.registerMovieDetailsButton.setOnClickListener {
+ moviesDialogVM.register(binding.movieDetails!!)
+ }
+
return binding.root
}
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/FavoritesFragment.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/FavoritesFragment.kt
new file mode 100644
index 0000000..97aed80
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/fragments/FavoritesFragment.kt
@@ -0,0 +1,52 @@
+package fr.iut.pm.movieapplication.ui.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import fr.iut.pm.movieapplication.databinding.FragmentFavoritesCategoryBinding
+import fr.iut.pm.movieapplication.ui.adapter.MovieAdapter
+import fr.iut.pm.movieapplication.ui.interfaces.MovieSelection
+import fr.iut.pm.movieapplication.ui.viewmodel.FavoritesVM
+
+class FavoritesFragment : Fragment(), MovieSelection {
+
+ private val favoritesVM by viewModels()
+
+ private val movieAdapter = MovieAdapter(this);
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val binding = FragmentFavoritesCategoryBinding.inflate(inflater)
+
+ binding.favoritesVM = favoritesVM
+ binding.lifecycleOwner = viewLifecycleOwner
+
+ with(binding.moviesItemRecyclerView) {
+ this.adapter = movieAdapter
+ }
+
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ favoritesVM.getFavoritesLiveData().observe(viewLifecycleOwner) {
+ movieAdapter.submitList(it)
+ }
+ }
+
+
+
+
+
+ override fun onMovieSelected(movieId: Int) {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/FavoritesVM.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/FavoritesVM.kt
new file mode 100644
index 0000000..5667f7d
--- /dev/null
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/FavoritesVM.kt
@@ -0,0 +1,30 @@
+package fr.iut.pm.movieapplication.ui.viewmodel
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import fr.iut.pm.movieapplication.data.database.MovieDataBase
+import fr.iut.pm.movieapplication.model.media.movie.Movie
+import fr.iut.pm.movieapplication.repository.local.MovieLocalRepository
+import kotlinx.coroutines.launch
+
+class FavoritesVM : ViewModel() {
+
+ private val repository = MovieLocalRepository(MovieDataBase.getInstance().movieDAO())
+
+ private var _favoritesLiveData : MutableLiveData> = MutableLiveData()
+
+ fun getFavoritesLiveData() : MutableLiveData> = _favoritesLiveData
+
+
+ init {
+ //with dispatchers.IO
+ viewModelScope.launch{
+ _favoritesLiveData.value = repository.getAllMovies()
+ }
+
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesDialogVM.kt b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesDialogVM.kt
index b39350f..ea482ef 100644
--- a/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesDialogVM.kt
+++ b/Sources/app/src/main/java/fr/iut/pm/movieapplication/ui/viewmodel/MoviesDialogVM.kt
@@ -1,13 +1,18 @@
package fr.iut.pm.movieapplication.ui.viewmodel
import androidx.lifecycle.*
+import fr.iut.pm.movieapplication.data.database.MovieDataBase
import fr.iut.pm.movieapplication.model.media.movie.MovieDetails
-import fr.iut.pm.movieapplication.repository.MovieRepository
+import fr.iut.pm.movieapplication.repository.MovieAPIRepository
+import fr.iut.pm.movieapplication.repository.local.MovieLocalRepository
import kotlinx.coroutines.launch
class MoviesDialogVM(private val movieId : Int) : ViewModel() {
- private val repository = MovieRepository()
+ private val repository = MovieAPIRepository()
+
+ private val movieLocalRepository = MovieLocalRepository(
+ MovieDataBase.getInstance().movieDAO())
private var _movieDetailsLiveData : MutableLiveData = MutableLiveData()
fun getMovieDetailLiveData() : LiveData = _movieDetailsLiveData
@@ -18,6 +23,11 @@ class MoviesDialogVM(private val movieId : Int) : ViewModel() {
}
}
+ fun register(movieDetails: MovieDetails) = viewModelScope.launch {
+
+ movieLocalRepository.insertMovieDetails(movieDetails)
+ }
+
}
class MoviesDialogVMFactory(private val movieId : Int) : ViewModelProvider.Factory
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 8c6da20..23ce2cb 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
@@ -4,17 +4,15 @@ import androidx.lifecycle.*
import androidx.recyclerview.widget.GridLayoutManager
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.repository.MovieAPIRepository
import fr.iut.pm.movieapplication.utils.Constants.Companion.MAX_PAGE
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MoviesVM() : ViewModel() {
/**
* The movie repository used to get our data
*/
- private val repository = MovieRepository()
+ private val repository = MovieAPIRepository()
/**
* The MutableLiveData
diff --git a/Sources/app/src/main/res/layout/fragment_favorites_category.xml b/Sources/app/src/main/res/layout/fragment_favorites_category.xml
new file mode 100644
index 0000000..424be29
--- /dev/null
+++ b/Sources/app/src/main/res/layout/fragment_favorites_category.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Sources/app/src/main/res/layout/movie_dialog.xml b/Sources/app/src/main/res/layout/movie_dialog.xml
index ee7df69..c8d5dbc 100644
--- a/Sources/app/src/main/res/layout/movie_dialog.xml
+++ b/Sources/app/src/main/res/layout/movie_dialog.xml
@@ -60,16 +60,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
android:text="@{movieDetails.overview.length() > 150 ? movieDetails.overview.substring(0, 150) + `...` : movieDetails.overview}"
android:textAlignment="center"
- app:layout_constraintBottom_toTopOf="@+id/button"
+ app:layout_constraintBottom_toTopOf="@+id/register_movie_details_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/details_image"
app:layout_constraintTop_toBottomOf="@+id/details_image" />
+ android:title="@string/bottom_favorite_item" />
\ No newline at end of file
diff --git a/Sources/app/src/main/res/menu/bottom_navigation_menu.xml b/Sources/app/src/main/res/menu/bottom_navigation_menu.xml
index 26edad9..e97491d 100644
--- a/Sources/app/src/main/res/menu/bottom_navigation_menu.xml
+++ b/Sources/app/src/main/res/menu/bottom_navigation_menu.xml
@@ -14,7 +14,7 @@
android:icon="@drawable/ic_tv_shows"
android:title="@string/bottom_series_item" />
+ android:title="@string/bottom_favorite_item" />
\ 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 efd0b3a..d8e800a 100644
--- a/Sources/app/src/main/res/values/strings.xml
+++ b/Sources/app/src/main/res/values/strings.xml
@@ -4,7 +4,7 @@
Accueil
Films
Séries
- Artistes
+ Favoris
Bienvenue,
diff --git a/Sources/build.gradle b/Sources/build.gradle
index ad7fa55..dcbfb79 100644
--- a/Sources/build.gradle
+++ b/Sources/build.gradle
@@ -7,7 +7,7 @@ plugins {
ext {
activityVersion = '1.6.1'
- appCompatVersion = '1.6.0'
+ appCompatVersion = '1.6.1'
constraintLayoutVersion = '2.1.4'
coreTestingVersion = '2.1.0'
coroutines = '1.6.4'