From 5a9e71d0a6625f0a2f501d5592870257f08bf772 Mon Sep 17 00:00:00 2001 From: Owen LeJeune Date: Wed, 21 Jun 2023 16:28:07 -0400 Subject: [PATCH] refactor account tabs to use paging --- .../tvtime/api/tmdb/api/BasePagingSource.kt | 64 ++++++ .../tvtime/api/tmdb/api/v3/AccountApi.kt | 42 ---- .../tvtime/api/tmdb/api/v3/AccountService.kt | 39 ---- .../tvtime/api/tmdb/api/v3/MoviesService.kt | 41 ---- .../tvtime/api/tmdb/api/v3/SearchService.kt | 38 ---- .../tvtime/api/tmdb/api/v3/TvService.kt | 41 ---- .../tmdb/api/v3/model/HomePagePagingSource.kt | 62 ------ .../v3/model/HomePagePeoplePagingSource.kt | 41 ---- .../api/tmdb/api/v3/model/RatedEpisode.kt | 19 -- .../api/tmdb/api/v3/model/RatedMedia.kt | 20 -- .../tmdb/api/v3/model/RatedMediaResponse.kt | 10 - .../tmdb/api/v3/model/RatedTopLevelMedia.kt | 20 -- .../v3/model/RecommendedMediaPagingSource.kt | 46 ----- .../tmdb/api/v3/model/WatchlistResponse.kt | 10 - .../tvtime/api/tmdb/api/v4/AccountV4Api.kt | 24 +-- .../api/tmdb/api/v4/AccountV4Service.kt | 34 ++-- .../tvtime/api/tmdb/api/v4/ListV4Service.kt | 13 +- .../model/{V4RatedMedia.kt => RatedMedia.kt} | 6 +- .../tmdb/api/{v3 => v4}/model/RatedMovie.kt | 8 +- .../api/tmdb/api/{v3 => v4}/model/RatedTv.kt | 6 +- .../api/tmdb/api/v4/model/V4RatedMovie.kt | 24 --- .../tvtime/api/tmdb/api/v4/model/V4RatedTv.kt | 23 --- .../tvtime/ui/components/Actions.kt | 4 +- .../tvtime/ui/components/Dialogs.kt | 9 +- .../tvtime/ui/navigation/AccountTabNavItem.kt | 81 ++++---- .../tvtime/ui/navigation/MediaTabNavItem.kt | 40 ++-- .../tvtime/ui/screens/AccountScreen.kt | 88 +++----- .../tvtime/ui/screens/ListDetailScreen.kt | 9 +- .../tvtime/ui/screens/MediaDetailScreen.kt | 2 +- .../tvtime/ui/screens/tabs/MediaTab.kt | 26 +-- .../tvtime/ui/screens/tabs/PeopleTab.kt | 7 +- .../tvtime/ui/viewmodel/AccountViewModel.kt | 91 +++++++++ .../tvtime/ui/viewmodel/MainViewModel.kt | 83 ++++++-- .../tvtime/ui/viewmodel/MediaTabViewModel.kt | 34 ---- .../tvtime/ui/viewmodel/PeopleTabViewModel.kt | 19 -- .../ui/viewmodel/RecommendedMediaViewModel.kt | 24 --- .../tvtime/ui/viewmodel/SearchViewModel.kt | 27 +-- .../tvtime/ui/viewmodel/ViewModelConstants.kt | 2 +- .../tvtime/utils/SessionManager.kt | 192 +----------------- app/src/main/res/values/strings.xml | 1 + 40 files changed, 394 insertions(+), 976 deletions(-) create mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/BasePagingSource.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePagingSource.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePeoplePagingSource.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedEpisode.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMedia.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMediaResponse.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTopLevelMedia.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RecommendedMediaPagingSource.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/WatchlistResponse.kt rename app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/{V4RatedMedia.kt => RatedMedia.kt} (88%) rename app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/{v3 => v4}/model/RatedMovie.kt (79%) rename app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/{v3 => v4}/model/RatedTv.kt (86%) delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMovie.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedTv.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MediaTabViewModel.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/PeopleTabViewModel.kt delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/RecommendedMediaViewModel.kt diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/BasePagingSource.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/BasePagingSource.kt new file mode 100644 index 0000000..f63220e --- /dev/null +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/BasePagingSource.kt @@ -0,0 +1,64 @@ +package com.owenlejeune.tvtime.api.tmdb.api + +import android.content.Context +import android.widget.Toast +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import androidx.paging.PagingSource +import androidx.paging.PagingState +import androidx.paging.cachedIn +import com.owenlejeune.tvtime.R +import com.owenlejeune.tvtime.ui.viewmodel.ViewModelConstants +import kotlinx.coroutines.flow.Flow +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import retrofit2.Response + +fun ViewModel.createPagingFlow( + fetcher: suspend (Int) -> Response, + processor: (S) -> List +): Flow> { + return Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) { + BasePagingSource( + fetcher = fetcher, + processor = processor + ) + }.flow.cachedIn(viewModelScope) +} + +class BasePagingSource( + private val fetcher: suspend (Int) -> Response, + private val processor: (S) -> List +): PagingSource(), KoinComponent { + + private val context: Context by inject() + + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition + } + + override suspend fun load(params: LoadParams): LoadResult { + return try { + val page = params.key ?: 1 + val response = fetcher(page) + if (response.isSuccessful) { + val responseBody = response.body() + val results = responseBody?.let(processor) ?: emptyList() + LoadResult.Page( + data = results, + prevKey = if (page == 1) { null } else { page - 1}, + nextKey = if (results.isEmpty()) { null } else { page + 1} + ) + } else { + Toast.makeText(context, context.getString(R.string.no_result_found), Toast.LENGTH_SHORT).show() + LoadResult.Invalid() + } + } catch (e: Exception) { + return LoadResult.Error(e) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountApi.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountApi.kt index 36868da..c0de98f 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountApi.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountApi.kt @@ -9,54 +9,12 @@ interface AccountApi { @GET("account") suspend fun getAccountDetails(): Response - @GET("account/{id}/favorite/movies") - suspend fun getFavoriteMovies( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - - @GET("account/{id}/favorite/tv") - suspend fun getFavoriteTvShows( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - @POST("account/{id}/favorite") suspend fun markAsFavorite( @Path("id") id: Int, @Body body: MarkAsFavoriteBody ): Response - @GET("account/{id}/rated/movies") - suspend fun getRatedMovies( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - - @GET("account/{id}/rated/tv") - suspend fun getRatedTvShows( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - - @GET("account/{id}/rated/tv/episodes") - suspend fun getRatedTvEpisodes( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - - @GET("account/{id}/watchlist/movies") - suspend fun getMovieWatchlist( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - - @GET("account/{id}/watchlist/tv") - suspend fun getTvWatchlist( - @Path("id") id: Int, - @Query("page") page: Int - ): Response> - @POST("account/{id}/watchlist") suspend fun addToWatchlist( @Path("id") id: Int, diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountService.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountService.kt index dddeae2..d3132d5 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountService.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AccountService.kt @@ -2,18 +2,8 @@ package com.owenlejeune.tvtime.api.tmdb.api.v3 import android.util.Log import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AccountDetails -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteMediaResponse -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteMovie -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteTvSeries import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MarkAsFavoriteBody -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedEpisode -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedMediaResponse -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedTv import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistBody -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistMovie -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistResponse -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistTvSeries import org.koin.core.component.KoinComponent import org.koin.core.component.inject import retrofit2.Response @@ -46,33 +36,4 @@ class AccountService: KoinComponent { } } - // TODO - replace these with account states API calls - suspend fun getFavoriteMovies(accountId: Int, page: Int = 1): Response> { - return accountService.getFavoriteMovies(accountId, page) - } - - suspend fun getFavoriteTvShows(accountId: Int, page: Int = 1): Response> { - return accountService.getFavoriteTvShows(accountId, page) - } - - suspend fun getRatedMovies(accountId: Int, page: Int = 1): Response> { - return accountService.getRatedMovies(accountId, page) - } - - suspend fun getRatedTvShows(accountId: Int, page: Int = 1): Response> { - return accountService.getRatedTvShows(accountId, page) - } - - suspend fun getRatedTvEpisodes(accountId: Int, page: Int = 1): Response> { - return accountService.getRatedTvEpisodes(accountId, page) - } - - suspend fun getMovieWatchlist(accountId: Int, page: Int = 1): Response> { - return accountService.getMovieWatchlist(accountId, page) - } - - suspend fun getTvWatchlist(accountId: Int, page: Int = 1): Response> { - return accountService.getTvWatchlist(accountId, page) - } - } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/MoviesService.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/MoviesService.kt index 7793844..b17ec8f 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/MoviesService.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/MoviesService.kt @@ -106,7 +106,6 @@ class MoviesService: KoinComponent, DetailService, HomePageService { } else { Log.d(TAG, "Issue getting account states: $response") } -// movieService.getAccountStates(id) storedIn { accountStates[id] = it } } suspend fun getReleaseDates(id: Int) { @@ -118,7 +117,6 @@ class MoviesService: KoinComponent, DetailService, HomePageService { val response = movieService.postMovieRatingAsUser(id, session.sessionId, ratingBody) if (response.isSuccessful) { Log.d(TAG, "Successfully rated") - SessionManager.currentSession.value?.refresh(SessionManager.Session.Changed.Rated) getAccountStates(id) } else { Log.w(TAG, "Issue posting rating") @@ -130,7 +128,6 @@ class MoviesService: KoinComponent, DetailService, HomePageService { val response = movieService.deleteMovieReviewAsUser(id, session.sessionId) if (response.isSuccessful) { Log.d(TAG, "Successfully deleted rated") - SessionManager.currentSession.value?.refresh(SessionManager.Session.Changed.Rated) getAccountStates(id) } else { Log.w(TAG, "Issue deleting rating") @@ -158,41 +155,3 @@ class MoviesService: KoinComponent, DetailService, HomePageService { return movieService.getUpcomingMovies(page) } } - -class SimilarMoviesSource(private val movieId: Int): PagingSource(), KoinComponent { - - private val service: MoviesService by inject() - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - val response = service.getSimilar(movieId, nextPage) - if (response.isSuccessful) { - val responseBody = response.body() - val result = responseBody?.results ?: emptyList() - LoadResult.Page( - data = result, - prevKey = if (nextPage == 1) { - null - } else { - nextPage - 1 - }, - nextKey = if (result.isEmpty()) { - null - } else { - responseBody?.page?.plus(1) ?: (nextPage + 1) - } - ) - } else { - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/SearchService.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/SearchService.kt index 508cf7f..a96c648 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/SearchService.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/SearchService.kt @@ -58,41 +58,3 @@ class SearchService: KoinComponent { } typealias SearchResultProvider = suspend (Int) -> Response> - -class SearchPagingSource( - private val provideResults: SearchResultProvider -): PagingSource(), KoinComponent { - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - val response = provideResults(nextPage) - if (response.isSuccessful) { - val responseBody = response.body() - val result = responseBody?.results ?: emptyList() - LoadResult.Page( - data = result, - prevKey = if (nextPage == 1) { - null - } else { - nextPage - 1 - }, - nextKey = if (result.isEmpty()) { - null - } else { - responseBody?.page?.plus(1) ?: (nextPage + 1) - } - ) - } else { - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/TvService.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/TvService.kt index 2651876..1eec62f 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/TvService.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/TvService.kt @@ -122,7 +122,6 @@ class TvService: KoinComponent, DetailService, HomePageService { val response = service.postTvRatingAsUser(id, session.sessionId, ratingBody) if (response.isSuccessful) { Log.d(TAG, "Successfully posted rating") - SessionManager.currentSession.value?.refresh(SessionManager.Session.Changed.Rated) } else { Log.w(TAG, "Issue posting rating") } @@ -133,13 +132,11 @@ class TvService: KoinComponent, DetailService, HomePageService { val response = service.deleteTvReviewAsUser(id, session.sessionId) if (response.isSuccessful) { Log.d(TAG, "Successfully deleted rating") - SessionManager.currentSession.value?.refresh(SessionManager.Session.Changed.Rated) } else { Log.w(TAG, "Issue deleting rating") } } - //todo - turn this into paging override suspend fun getSimilar(id: Int, page: Int): Response { return service.getSimilarTvShows(id, page) } @@ -161,41 +158,3 @@ class TvService: KoinComponent, DetailService, HomePageService { } } - -class SimilarTvSource(private val tvId: Int): PagingSource(), KoinComponent { - - private val service: TvService by inject() - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - val response = service.getSimilar(tvId, nextPage) - if (response.isSuccessful) { - val responseBody = response.body() - val result = responseBody?.results ?: emptyList() - LoadResult.Page( - data = result, - prevKey = if (nextPage == 1) { - null - } else { - nextPage - 1 - }, - nextKey = if (result.isEmpty()) { - null - } else { - responseBody?.page?.plus(1) ?: (nextPage + 1) - } - ) - } else { - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePagingSource.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePagingSource.kt deleted file mode 100644 index 05a7ee4..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePagingSource.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import android.content.Context -import android.util.Log -import android.widget.Toast -import androidx.paging.PagingSource -import androidx.paging.PagingState -import com.owenlejeune.tvtime.R -import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService -import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun -import org.koin.core.Koin -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject -import retrofit2.Response - -class HomePagePagingSource( - private val service: HomePageService, - private val mediaFetch: MediaFetchFun, - private val tag: String -): PagingSource(), KoinComponent { - - companion object { - val TAG = HomePagePagingSource::class.java.simpleName - } - - private val context: Context by inject() - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - Log.d(TAG, "Loading $tag page $nextPage") - val mediaResponse = mediaFetch.invoke(service, nextPage) - if (mediaResponse.isSuccessful) { - val responseBody = mediaResponse.body() - val results = responseBody?.results ?: emptyList() - LoadResult.Page( - data = results, - prevKey = if (nextPage == 1) { - null - } else { - nextPage - 1 - }, - nextKey = if (results.isEmpty() || responseBody == null) { - null - } else { - responseBody.page + 1 - } - ) - } else { - Toast.makeText(context, context.getString(R.string.no_result_found), Toast.LENGTH_SHORT).show() - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePeoplePagingSource.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePeoplePagingSource.kt deleted file mode 100644 index 4351db8..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/HomePagePeoplePagingSource.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import android.content.Context -import android.util.Log -import android.widget.Toast -import androidx.paging.PagingSource -import androidx.paging.PagingState -import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleApi -import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject - -class HomePagePeoplePagingSource: PagingSource(), KoinComponent { - - private val service: PeopleService by inject() - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - val peopleResponse = service.getPopular(page = nextPage) - if (peopleResponse.isSuccessful) { - val responseBody = peopleResponse.body() - val results = responseBody?.results ?: emptyList() - LoadResult.Page( - data = results, - prevKey = if (nextPage == 1) null else nextPage - 1, - nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1 - ) - } else { - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedEpisode.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedEpisode.kt deleted file mode 100644 index 51e11d4..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedEpisode.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import com.google.gson.annotations.SerializedName - -class RatedEpisode( - type: RatedType, - id: Int, - overview: String, - name: String, - voteAverage: Float, - voteCount: Int, - rating: Float, - releaseDate: String, - @SerializedName("episode_number") val episodeNumber: Int, - @SerializedName("production_code") val productionCode: String?, - @SerializedName("season_number") val seasonNumber: Int, - @SerializedName("show_id") val showId: Int, - @SerializedName("still_path") val stillPath: String?, -): RatedMedia(RatedType.EPISODE, id, overview, name, voteAverage, voteCount, rating, releaseDate) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMedia.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMedia.kt deleted file mode 100644 index 0fa7fe6..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMedia.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import com.google.gson.annotations.SerializedName - -abstract class RatedMedia( - var type: RatedType, - @SerializedName("id") val id: Int, - @SerializedName("overview") val overview: String, - @SerializedName("name", alternate = ["title"]) val name: String, - @SerializedName("vote_average") val voteAverage: Float, - @SerializedName("vote_count") val voteCount: Int, - @SerializedName("rating") val rating: Float, - @SerializedName("release_date", alternate = ["first_air_date", "air_date"]) val releaseDate: String -) { - enum class RatedType { - MOVIE, - SERIES, - EPISODE - } -} diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMediaResponse.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMediaResponse.kt deleted file mode 100644 index 96decb4..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMediaResponse.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import com.google.gson.annotations.SerializedName - -class RatedMediaResponse( - @SerializedName("page") val page: Int, - @SerializedName("results") val results: List, - @SerializedName("total_pages") val totalPages: Int, - @SerializedName("total_results") val totalResults: Int -) diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTopLevelMedia.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTopLevelMedia.kt deleted file mode 100644 index 6537dc9..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTopLevelMedia.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import com.google.gson.annotations.SerializedName - -abstract class RatedTopLevelMedia( - type: RatedType, - id: Int, - overview: String, - name: String, - voteAverage: Float, - voteCount: Int, - rating: Float, - releaseDate: String, - @SerializedName("backdrop_path") val backdropPath: String?, - @SerializedName("genre_ids") val genreIds: List, - @SerializedName("original_language") val originalLanguage: String, - @SerializedName("original_name", alternate = ["original_title"]) val originalName: String, - @SerializedName("poster_path") val posterPath: String?, - @SerializedName("popularity") val popularity: Float, -): RatedMedia(type, id, overview, name, voteAverage, voteCount, rating, releaseDate) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RecommendedMediaPagingSource.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RecommendedMediaPagingSource.kt deleted file mode 100644 index 2ea2648..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RecommendedMediaPagingSource.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import androidx.paging.PagingSource -import androidx.paging.PagingState -import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Service -import com.owenlejeune.tvtime.preferences.AppPreferences -import com.owenlejeune.tvtime.utils.types.MediaViewType -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject - -class RecommendedMediaPagingSource( - private val mediaType: MediaViewType -): PagingSource(), KoinComponent { - - private val preferences: AppPreferences by inject() - private val service: AccountV4Service by inject() - - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition - } - - override suspend fun load(params: LoadParams): LoadResult { - return try { - val nextPage = params.key ?: 1 - val mediaResponse = if (mediaType == MediaViewType.MOVIE) { - service.getRecommendedMovies(preferences.authorizedSessionValues?.accountId ?: "", nextPage) - } else { - service.getRecommendedTvSeries(preferences.authorizedSessionValues?.accountId ?: "", nextPage) - } - if (mediaResponse.isSuccessful) { - val responseBody = mediaResponse.body() - val results = responseBody?.results ?: emptyList() - LoadResult.Page( - data = results, - prevKey = if (nextPage == 1) null else nextPage - 1, - nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1 - ) - } else { - LoadResult.Invalid() - } - } catch (e: Exception) { - return LoadResult.Error(e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/WatchlistResponse.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/WatchlistResponse.kt deleted file mode 100644 index 0ed71c6..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/WatchlistResponse.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model - -import com.google.gson.annotations.SerializedName - -class WatchlistResponse( - @SerializedName("page") val page: Int, - @SerializedName("results") val results: List, - @SerializedName("total_pages") val totalPages: Int, - @SerializedName("total_results") val totalResults: Int -) diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Api.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Api.kt index 8ddf377..c939b83 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Api.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Api.kt @@ -2,12 +2,14 @@ package com.owenlejeune.tvtime.api.tmdb.api.v4 import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteMovie import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteTvSeries -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedTv +import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistMovie +import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistTvSeries import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountList import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountResponse -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.V4RatedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.V4RatedTv +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedTv +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedTv import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path @@ -24,23 +26,17 @@ interface AccountV4Api { @GET("account/{account_id}/tv/favorites") suspend fun getFavoriteTvShows(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> - @GET("account/{account_id}/movie/recommendations") - suspend fun getMovieRecommendations(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> - - @GET("account/{account_id}/tv/recommendations") - suspend fun getTvShowRecommendations(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> - @GET("account/{account_id}/movie/watchlist") - suspend fun getMovieWatchlist(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> + suspend fun getMovieWatchlist(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> @GET("account/{account_id}/tv/watchlist") - suspend fun getTvShowWatchlist(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> + suspend fun getTvShowWatchlist(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> @GET("account/{account_id}/movie/rated") - suspend fun getRatedMovies(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> + suspend fun getRatedMovies(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> @GET("account/{account_id}/tv/rated") - suspend fun getRatedTvShows(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> + suspend fun getRatedTvShows(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> @GET("account/{account_id}/movie/recommendations") suspend fun getRecommendedMovies(@Path("account_id") accountId: String, @Query("page") page: Int = 1): Response> diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Service.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Service.kt index 87dce1c..15158ac 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Service.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/AccountV4Service.kt @@ -3,55 +3,49 @@ package com.owenlejeune.tvtime.api.tmdb.api.v4 import com.owenlejeune.tvtime.api.tmdb.TmdbClient import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteMovie import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteTvSeries -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedTv +import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistMovie +import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistTvSeries import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountList import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountResponse -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.V4RatedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.V4RatedTv +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedTv +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedTv import retrofit2.Response class AccountV4Service { private val service by lazy { TmdbClient().createV4AccountService() } - suspend fun getLists(accountId: String, page: Int = 1): Response> { + suspend fun getLists(accountId: String, page: Int): Response> { return service.getLists(accountId, page) } - suspend fun getFavoriteMovies(accountId: String, page: Int = 1): Response> { + suspend fun getFavoriteMovies(accountId: String, page: Int): Response> { return service.getFavoriteMovies(accountId, page) } - suspend fun getFavoriteTvShows(accountId: String, page: Int = 1): Response> { + suspend fun getFavoriteTvShows(accountId: String, page: Int): Response> { return service.getFavoriteTvShows(accountId, page) } - suspend fun getMovieRecommendations(accountId: String, page: Int = 1): Response> { - return service.getMovieRecommendations(accountId, page) - } - - suspend fun getTvShowRecommendations(accountId: String, page: Int = 1): Response> { - return service.getTvShowRecommendations(accountId, page) - } - - suspend fun getMovieWatchlist(accountId: String, page: Int = 1): Response> { + suspend fun getMovieWatchlist(accountId: String, page: Int): Response> { return service.getMovieWatchlist(accountId, page) } - suspend fun getTvShowWatchlist(accountId: String, page: Int = 1): Response> { + suspend fun getTvShowWatchlist(accountId: String, page: Int): Response> { return service.getTvShowWatchlist(accountId, page) } - suspend fun getRatedMovies(accountId: String, page: Int = 1): Response> { + suspend fun getRatedMovies(accountId: String, page: Int): Response> { return service.getRatedMovies(accountId, page) } - suspend fun getRatedTvShows(accountId: String, page: Int = 1): Response> { + suspend fun getRatedTvShows(accountId: String, page: Int): Response> { return service.getRatedTvShows(accountId, page) } - suspend fun getRecommendedMovies(accountId: String, page: Int = 1): Response> { + suspend fun getRecommendedMovies(accountId: String, page: Int ): Response> { return service.getRecommendedMovies(accountId, page) } diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/ListV4Service.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/ListV4Service.kt index 42abe89..369cef5 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/ListV4Service.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/ListV4Service.kt @@ -2,14 +2,14 @@ package com.owenlejeune.tvtime.api.tmdb.api.v4 import android.util.Log import androidx.compose.runtime.mutableStateMapOf -import com.owenlejeune.tvtime.BuildConfig -import com.owenlejeune.tvtime.api.tmdb.TmdbClient -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.* -import com.owenlejeune.tvtime.preferences.AppPreferences -import com.owenlejeune.tvtime.utils.SessionManager +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AddToListBody +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.CreateListBody +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.DeleteListItemsBody +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListUpdateBody +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.MediaList +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.UpdateListItemBody import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import retrofit2.Response class ListV4Service: KoinComponent { @@ -47,7 +47,6 @@ class ListV4Service: KoinComponent { suspend fun deleteListItems(listId: Int, body: DeleteListItemsBody) { val response = service.deleteListItems(listId, body) if (response.isSuccessful) { - SessionManager.currentSession.value?.refresh(SessionManager.Session.Changed.List) getList(listId) } } diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMedia.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMedia.kt similarity index 88% rename from app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMedia.kt rename to app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMedia.kt index aea1baa..5ddf373 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMedia.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMedia.kt @@ -2,14 +2,14 @@ package com.owenlejeune.tvtime.api.tmdb.api.v4.model import com.google.gson.annotations.SerializedName -abstract class V4RatedMedia( +abstract class RatedMedia( var type: RatedType, @SerializedName("id") val id: Int, @SerializedName("overview") val overview: String, @SerializedName("name", alternate = ["title"]) val name: String, @SerializedName("vote_average") val voteAverage: Float, @SerializedName("vote_count") val voteCount: Int, - @SerializedName("rating") val rating: AccountRating, + @SerializedName("account_rating") val rating: AccountRating, @SerializedName("release_date", alternate = ["first_air_date", "air_date"]) val releaseDate: String, @SerializedName("backdrop_path") val backdropPath: String?, @SerializedName("genre_ids") val genreIds: List, @@ -25,7 +25,7 @@ abstract class V4RatedMedia( } inner class AccountRating( - @SerializedName("value") val rating: Int, + @SerializedName("value") val value: Float, @SerializedName("created_at") val createdAt: String ) } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMovie.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMovie.kt similarity index 79% rename from app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMovie.kt rename to app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMovie.kt index 10dd040..fbe2d8a 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedMovie.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedMovie.kt @@ -1,4 +1,4 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model +package com.owenlejeune.tvtime.api.tmdb.api.v4.model import com.google.gson.annotations.SerializedName @@ -8,7 +8,7 @@ class RatedMovie( name: String, voteAverage: Float, voteCount: Int, - rating: Float, + rating: AccountRating, backdropPath: String?, genreIds: List, originalLanguage: String, @@ -17,8 +17,8 @@ class RatedMovie( popularity: Float, releaseDate: String, @SerializedName("adult") val isAdult: Boolean, - @SerializedName("video") val video: Boolean, -): RatedTopLevelMedia( + @SerializedName("video") val video: Boolean +): RatedMedia( RatedType.MOVIE, id, overview, name, voteAverage, voteCount, rating, releaseDate, backdropPath, genreIds, originalLanguage, originalName, posterPath, popularity ) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTv.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedTv.kt similarity index 86% rename from app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTv.kt rename to app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedTv.kt index 13be6a5..82ee8e7 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/RatedTv.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/RatedTv.kt @@ -1,4 +1,4 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v3.model +package com.owenlejeune.tvtime.api.tmdb.api.v4.model import com.google.gson.annotations.SerializedName @@ -8,7 +8,7 @@ class RatedTv( name: String, voteAverage: Float, voteCount: Int, - rating: Float, + rating: AccountRating, backdropPath: String?, genreIds: List, originalLanguage: String, @@ -17,7 +17,7 @@ class RatedTv( popularity: Float, releaseDate: String, @SerializedName("origin_country") val originCountry: List, -): RatedTopLevelMedia( +): RatedMedia( RatedType.SERIES, id, overview, name, voteAverage, voteCount, rating, releaseDate, backdropPath, genreIds, originalLanguage, originalName, posterPath, popularity ) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMovie.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMovie.kt deleted file mode 100644 index 8898bb9..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedMovie.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v4.model - -import com.google.gson.annotations.SerializedName - -class V4RatedMovie( - id: Int, - overview: String, - name: String, - voteAverage: Float, - voteCount: Int, - rating: AccountRating, - backdropPath: String?, - genreIds: List, - originalLanguage: String, - originalName: String, - posterPath: String?, - popularity: Float, - releaseDate: String, - @SerializedName("adult") val isAdult: Boolean, - @SerializedName("video") val video: Boolean -): V4RatedMedia( - RatedType.MOVIE, id, overview, name, voteAverage, voteCount, rating, releaseDate, - backdropPath, genreIds, originalLanguage, originalName, posterPath, popularity -) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedTv.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedTv.kt deleted file mode 100644 index e8e0437..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v4/model/V4RatedTv.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.owenlejeune.tvtime.api.tmdb.api.v4.model - -import com.google.gson.annotations.SerializedName - -class V4RatedTv( - id: Int, - overview: String, - name: String, - voteAverage: Float, - voteCount: Int, - rating: AccountRating, - backdropPath: String?, - genreIds: List, - originalLanguage: String, - originalName: String, - posterPath: String?, - popularity: Float, - releaseDate: String, - @SerializedName("origin_country") val originCountry: List, -): V4RatedMedia( - RatedType.SERIES, id, overview, name, voteAverage, voteCount, rating, releaseDate, - backdropPath, genreIds, originalLanguage, originalName, posterPath, popularity -) \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Actions.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Actions.kt index f1e5190..b113dde 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Actions.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Actions.kt @@ -74,9 +74,7 @@ fun ActionsView( } Row( - modifier = modifier - .wrapContentSize() - .padding(horizontal = 16.dp), + modifier = modifier, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { if (actions.contains(Actions.RATE)) { diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Dialogs.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Dialogs.kt index 41fef8f..9c6e8e1 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Dialogs.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Dialogs.kt @@ -1,7 +1,6 @@ package com.owenlejeune.tvtime.ui.components import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button @@ -34,7 +33,13 @@ fun RatingDialog( AlertDialog( modifier = Modifier.wrapContentHeight(), onDismissRequest = { showDialog.value = false }, - title = { Text(text = stringResource(R.string.rating_dialog_title)) }, + title = { + if (rating > 0f) { + Text(text = stringResource(id = R.string.my_rating_dialog_title)) + } else { + Text(text = stringResource(R.string.rating_dialog_title)) + } + }, confirmButton = { Button( modifier = Modifier.height(40.dp), diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AccountTabNavItem.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AccountTabNavItem.kt index e5ca603..a343436 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AccountTabNavItem.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AccountTabNavItem.kt @@ -5,17 +5,14 @@ import androidx.navigation.NavHostController import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteMovie import com.owenlejeune.tvtime.api.tmdb.api.v3.model.FavoriteTvSeries -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedEpisode -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedMovie -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatedTv import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistMovie import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistTvSeries import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountList +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedTv import com.owenlejeune.tvtime.ui.screens.AccountTabContent -import com.owenlejeune.tvtime.utils.types.MediaViewType -import com.owenlejeune.tvtime.ui.screens.RecommendedAccountTabContent import com.owenlejeune.tvtime.utils.ResourceUtils -import com.owenlejeune.tvtime.utils.SessionManager +import com.owenlejeune.tvtime.utils.types.MediaViewType import com.owenlejeune.tvtime.utils.types.TabNavItem import org.koin.core.component.inject import kotlin.reflect.KClass @@ -26,8 +23,8 @@ sealed class AccountTabNavItem( noContentStringRes: Int, val mediaType: MediaViewType, val screen: AccountNavComposableFun, - val listFetchFun: ListFetchFun, - val listType: KClass<*>, + val type: AccountTabType, + val contentType: KClass<*>, val ordinal: Int ): TabNavItem(route) { private val resourceUtils: ResourceUtils by inject() @@ -35,10 +32,18 @@ sealed class AccountTabNavItem( override val name = resourceUtils.getString(stringRes) val noContentText = resourceUtils.getString(noContentStringRes) + enum class AccountTabType { + RATED, + FAVORITE, + WATCHLIST, + LIST, + RECOMMENDED + } + companion object { val AuthorizedItems get() = listOf( - RatedMovies, RatedTvShows, RatedTvEpisodes, FavoriteMovies, FavoriteTvShows, + RatedMovies, RatedTvShows, /*RatedTvEpisodes, */FavoriteMovies, FavoriteTvShows, MovieWatchlist, TvWatchlist, UserLists, RecommendedMovies, RecommendedTv ).filter { it.ordinal > -1 }.sortedBy { it.ordinal } } @@ -49,7 +54,7 @@ sealed class AccountTabNavItem( R.string.no_rated_movies, MediaViewType.MOVIE, screenContent, - { SessionManager.currentSession.value?.ratedMovies ?: emptyList() }, + AccountTabType.RATED, RatedMovie::class, 0 ) @@ -59,27 +64,27 @@ sealed class AccountTabNavItem( R.string.no_rated_tv, MediaViewType.TV, screenContent, - { SessionManager.currentSession.value?.ratedTvShows ?: emptyList() }, + AccountTabType.RATED, RatedTv::class, 1 ) - object RatedTvEpisodes: AccountTabNavItem( - R.string.nav_rated_episodes_title, - "rated_episodes_route", - R.string.no_rated_episodes, - MediaViewType.EPISODE, - screenContent, - { SessionManager.currentSession.value?.ratedTvEpisodes ?: emptyList() }, - RatedEpisode::class, - -1 //2 - ) +// object RatedTvEpisodes: AccountTabNavItem( +// R.string.nav_rated_episodes_title, +// "rated_episodes_route", +// R.string.no_rated_episodes, +// MediaViewType.EPISODE, +// screenContent, +// AccountTabType.RATED, +// RatedEpisode::class, +// -1 //2 +// ) object FavoriteMovies: AccountTabNavItem( R.string.nav_favorite_movies_title, "favorite_movies_route", R.string.no_favorite_movies, MediaViewType.MOVIE, screenContent, - { SessionManager.currentSession.value?.favoriteMovies ?: emptyList() }, + AccountTabType.FAVORITE, FavoriteMovie::class, 3 ) @@ -89,7 +94,7 @@ sealed class AccountTabNavItem( R.string.no_favorite_tv, MediaViewType.TV, screenContent, - { SessionManager.currentSession.value?.favoriteTvShows ?: emptyList() }, + AccountTabType.FAVORITE, FavoriteTvSeries::class, 4 ) @@ -99,7 +104,7 @@ sealed class AccountTabNavItem( R.string.no_watchlist_movies, MediaViewType.MOVIE, screenContent, - { SessionManager.currentSession.value?.movieWatchlist ?: emptyList() }, + AccountTabType.WATCHLIST, WatchlistMovie::class, 5 ) @@ -109,7 +114,7 @@ sealed class AccountTabNavItem( R.string.no_watchlist_tv, MediaViewType.TV, screenContent, - { SessionManager.currentSession.value?.tvWatchlist ?: emptyList() }, + AccountTabType.WATCHLIST, WatchlistTvSeries::class, 6 ) @@ -120,7 +125,7 @@ sealed class AccountTabNavItem( R.string.no_lists, MediaViewType.LIST, screenContent, - { SessionManager.currentSession.value?.accountLists ?: emptyList() }, + AccountTabType.LIST, AccountList::class, 7 ) @@ -130,8 +135,8 @@ sealed class AccountTabNavItem( "recommended_movies_route", R.string.no_recommended_movies, MediaViewType.MOVIE, - recommendedScreenContent, - { emptyList() }, + screenContent, + AccountTabType.RECOMMENDED, AccountList::class, 8 ) @@ -141,31 +146,21 @@ sealed class AccountTabNavItem( "recommended_tv_route", R.string.no_recommended_tv, MediaViewType.TV, - recommendedScreenContent, - { emptyList() }, + screenContent, + AccountTabType.RECOMMENDED, AccountList::class, 9 ) } -private val screenContent: AccountNavComposableFun = { noContentText, appNavController, mediaViewType, listFetchFun, clazz -> +private val screenContent: AccountNavComposableFun = { noContentText, appNavController, mediaViewType, atType, clazz -> AccountTabContent( noContentText = noContentText, appNavController = appNavController, mediaViewType = mediaViewType, - listFetchFun = listFetchFun, + accountTabType = atType, clazz = clazz ) } -private val recommendedScreenContent: AccountNavComposableFun = { noContentText, appNavController, mediaViewType, _, _ -> - RecommendedAccountTabContent( - noContentText = noContentText, - appNavController = appNavController, - mediaViewType = mediaViewType, - ) -} - -typealias ListFetchFun = () -> List - -typealias AccountNavComposableFun = @Composable (String, NavHostController, MediaViewType, ListFetchFun, KClass<*>) -> Unit \ No newline at end of file +typealias AccountNavComposableFun = @Composable (String, NavHostController, MediaViewType, AccountTabNavItem.AccountTabType, KClass<*>) -> Unit \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/MediaTabNavItem.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/MediaTabNavItem.kt index 2dcb677..495fd43 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/MediaTabNavItem.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/MediaTabNavItem.kt @@ -5,11 +5,11 @@ import androidx.navigation.NavHostController import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse -import com.owenlejeune.tvtime.utils.types.MediaViewType -import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel import com.owenlejeune.tvtime.ui.screens.tabs.MediaTabContent import com.owenlejeune.tvtime.utils.ResourceUtils +import com.owenlejeune.tvtime.utils.types.MediaViewType import com.owenlejeune.tvtime.utils.types.TabNavItem +import com.owenlejeune.tvtime.utils.types.ViewableMediaTypeException import org.koin.core.component.inject import retrofit2.Response @@ -17,17 +17,31 @@ sealed class MediaTabNavItem( stringRes: Int, route: String, val screen: MediaNavComposableFun, - val movieViewModel: MediaTabViewModel?, - val tvViewModel: MediaTabViewModel? + val type: Type ): TabNavItem(route) { private val resourceUtils: ResourceUtils by inject() override val name = resourceUtils.getString(stringRes) + enum class Type { + POPULAR, + NOW_PLAYING, + UPCOMING, + TOP_RATED + } + companion object { val MovieItems = listOf(NowPlaying, Popular, Upcoming, TopRated) val TvItems = listOf(OnTheAir, Popular, AiringToday, TopRated) + fun itemsForType(type: MediaViewType): List { + return when (type) { + MediaViewType.MOVIE -> MovieItems + MediaViewType.TV -> TvItems + else -> throw ViewableMediaTypeException(type) + } + } + private val Items = listOf(NowPlaying, Popular, TopRated, Upcoming, AiringToday, OnTheAir) fun getByRoute(route: String?): MediaTabNavItem? { @@ -39,43 +53,37 @@ sealed class MediaTabNavItem( stringRes = R.string.nav_popular_title, route = "popular_route", screen = screenContent, - movieViewModel = MediaTabViewModel.PopularMoviesVM, - tvViewModel = MediaTabViewModel.PopularTvVM + type = Type.POPULAR ) object TopRated: MediaTabNavItem( stringRes = R.string.nav_top_rated_title, route = "top_rated_route", screen = screenContent, - movieViewModel = MediaTabViewModel.TopRatedMoviesVM, - tvViewModel = MediaTabViewModel.TopRatedTvVM + type = Type.TOP_RATED ) object NowPlaying: MediaTabNavItem( stringRes = R.string.nav_now_playing_title, route = "now_playing_route", screen = screenContent, - movieViewModel = MediaTabViewModel.NowPlayingMoviesVM, - tvViewModel = null + type = Type.NOW_PLAYING ) object Upcoming: MediaTabNavItem( stringRes = R.string.nav_upcoming_title, route = "upcoming_route", screen = screenContent, - movieViewModel = MediaTabViewModel.UpcomingMoviesVM, - tvViewModel = null + type = Type.UPCOMING ) object AiringToday: MediaTabNavItem( stringRes = R.string.nav_tv_airing_today_title, route = "airing_today_route", screen = screenContent, - movieViewModel = null, - tvViewModel = MediaTabViewModel.AiringTodayTvVM + type = Type.NOW_PLAYING ) object OnTheAir: MediaTabNavItem( stringRes = R.string.nav_tv_on_the_air, route = "on_the_air_route", screen = screenContent, - movieViewModel = null, - tvViewModel = MediaTabViewModel.OnTheAirTvVM + type = Type.UPCOMING ) } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/AccountScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/AccountScreen.kt index c7a933a..e09392a 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/AccountScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/AccountScreen.kt @@ -20,7 +20,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController +import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.HorizontalPager @@ -30,6 +32,10 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.api.tmdb.api.v3.model.* import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountList +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedMedia +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedMovie +import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RatedTv +import com.owenlejeune.tvtime.extensions.lazyPagingItems import com.owenlejeune.tvtime.extensions.unlessEmpty import com.owenlejeune.tvtime.ui.components.AccountIcon import com.owenlejeune.tvtime.ui.components.MediaResultCard @@ -37,8 +43,7 @@ import com.owenlejeune.tvtime.ui.components.PagingPosterGrid import com.owenlejeune.tvtime.ui.components.ScrollableTabs import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem import com.owenlejeune.tvtime.ui.navigation.AppNavItem -import com.owenlejeune.tvtime.ui.navigation.ListFetchFun -import com.owenlejeune.tvtime.ui.viewmodel.RecommendedMediaViewModel +import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel import com.owenlejeune.tvtime.utils.SessionManager import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.types.MediaViewType @@ -177,12 +182,13 @@ fun AccountTabContent( noContentText: String, appNavController: NavHostController, mediaViewType: MediaViewType, - listFetchFun: ListFetchFun, + accountTabType: AccountTabNavItem.AccountTabType, clazz: KClass ) { - val contentItems = remember { listFetchFun() } + val accountViewModel = viewModel() + val contentItems = accountViewModel.getPagingFlowFor(mediaViewType, accountTabType).collectAsLazyPagingItems() - if (contentItems.isEmpty()) { + if (contentItems.itemCount == 0) { Column { Spacer(modifier = Modifier.weight(1f)) Text( @@ -195,6 +201,15 @@ fun AccountTabContent( ) Spacer(modifier = Modifier.weight(1f)) } + } else if (accountTabType == AccountTabNavItem.AccountTabType.RECOMMENDED) { + PagingPosterGrid( + lazyPagingItems = contentItems as LazyPagingItems, + onClick = { id -> + appNavController.navigate( + AppNavItem.DetailView.withArgs(mediaViewType, id) + ) + } + ) } else { LazyColumn( modifier = Modifier @@ -202,10 +217,10 @@ fun AccountTabContent( .padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - items(contentItems.size) { i -> + lazyPagingItems(contentItems) { i -> when (clazz) { RatedTv::class, RatedMovie::class -> { - val item = contentItems[i] as RatedTopLevelMedia + val item = i as RatedMedia MediaItemRow( appNavController = appNavController, mediaViewType = mediaViewType, @@ -214,24 +229,12 @@ fun AccountTabContent( backdropPath = TmdbUtils.getFullBackdropPath(item.backdropPath), name = item.name, date = item.releaseDate, - rating = item.rating, - description = item.overview - ) - } - RatedEpisode::class -> { - val item = contentItems[i] as RatedMedia - MediaItemRow( - appNavController = appNavController, - mediaViewType = mediaViewType, - id = item.id, - name = item.name, - date = item.releaseDate, - rating = item.rating, + rating = item.rating.value, description = item.overview ) } FavoriteMovie::class, FavoriteTvSeries::class -> { - val item = contentItems[i] as FavoriteMedia + val item = i as FavoriteMedia MediaItemRow( appNavController = appNavController, mediaViewType = mediaViewType, @@ -244,7 +247,7 @@ fun AccountTabContent( ) } WatchlistMovie::class, WatchlistTvSeries::class -> { - val item = contentItems[i] as WatchlistMedia + val item = i as WatchlistMedia MediaItemRow( appNavController = appNavController, mediaViewType = mediaViewType, @@ -257,7 +260,7 @@ fun AccountTabContent( ) } AccountList::class -> { - val item = contentItems[i] as AccountList + val item = i as AccountList MediaItemRow( appNavController = appNavController, mediaViewType = mediaViewType, @@ -275,43 +278,6 @@ fun AccountTabContent( } } -@Composable -fun RecommendedAccountTabContent( - noContentText: String, - appNavController: NavHostController, - mediaViewType: MediaViewType, -) { - val viewModel = when (mediaViewType) { - MediaViewType.MOVIE -> RecommendedMediaViewModel.RecommendedMoviesVM - MediaViewType.TV -> RecommendedMediaViewModel.RecommendedTvVM - else -> throw IllegalArgumentException("Media type given: ${mediaViewType}, \n expected one of MediaViewType.MOVIE, MediaViewType.TV") // shouldn't happen - } - val mediaListItems = viewModel.mediaItems.collectAsLazyPagingItems() - - if (mediaListItems.itemCount < 1) { - Column { - Spacer(modifier = Modifier.weight(1f)) - Text( - modifier = Modifier.fillMaxWidth(), - text = noContentText, - color = MaterialTheme.colorScheme.onBackground, - fontSize = 22.sp, - textAlign = TextAlign.Center - ) - Spacer(modifier = Modifier.weight(1f)) - } - } else { - PagingPosterGrid( - lazyPagingItems = mediaListItems, - onClick = { id -> - appNavController.navigate( - AppNavItem.DetailView.withArgs(mediaViewType, id) - ) - } - ) - } -} - @Composable private fun MediaItemRow( appNavController: NavHostController, @@ -345,6 +311,6 @@ fun AccountTabs( appNavController: NavHostController ) { HorizontalPager(count = tabs.size, state = pagerState) { page -> - tabs[page].screen(tabs[page].noContentText, appNavController, tabs[page].mediaType, tabs[page].listFetchFun, tabs[page].listType) + tabs[page].screen(tabs[page].noContentText, appNavController, tabs[page].mediaType, tabs[page].type, tabs[page].contentType) } } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/ListDetailScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/ListDetailScreen.kt index 8f80f3a..d3093d5 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/ListDetailScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/ListDetailScreen.kt @@ -90,7 +90,6 @@ fun ListDetailScreen( val listMap = remember { accountViewModel.listMap } val parentList = listMap[itemId] - val decayAnimationSpec = rememberSplineBasedDecay() val topAppBarScrollState = rememberTopAppBarScrollState() val scrollBehavior = remember(decayAnimationSpec) { @@ -133,9 +132,7 @@ fun ListDetailScreen( val selectedSortOrder = remember { mutableStateOf(mediaList.sortBy) } ListHeader( list = mediaList, - selectedSortOrder = selectedSortOrder, - service = service, - parentList = parentList + selectedSortOrder = selectedSortOrder ) val sortedResults = selectedSortOrder.value.sort(mediaList.results) @@ -155,9 +152,7 @@ fun ListDetailScreen( @Composable private fun ListHeader( list: MediaList, - selectedSortOrder: MutableState, - service: ListV4Service, - parentList: MediaList? + selectedSortOrder: MutableState ) { val context = LocalContext.current diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt index 6c916b8..b8a40f2 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt @@ -204,7 +204,7 @@ private fun MediaViewContent( val currentSession = remember { SessionManager.currentSession } currentSession.value?.let { - ActionsView(itemId = itemId, type = type) + ActionsView(itemId = itemId, type = type, modifier = Modifier.padding(start = 20.dp)) } if (type == MediaViewType.MOVIE) { diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/MediaTab.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/MediaTab.kt index adb8a4b..5b3a06b 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/MediaTab.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/MediaTab.kt @@ -1,9 +1,7 @@ package com.owenlejeune.tvtime.ui.screens.tabs import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.ui.res.stringResource import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController @@ -16,11 +14,11 @@ import com.google.accompanist.pager.rememberPagerState import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.ui.components.PagingPosterGrid import com.owenlejeune.tvtime.ui.components.SearchView +import com.owenlejeune.tvtime.ui.components.Tabs import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem -import com.owenlejeune.tvtime.ui.components.Tabs import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel -import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel +import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.utils.types.MediaViewType @OptIn(ExperimentalPagerApi::class) @@ -44,11 +42,7 @@ fun MediaTab( mediaType = mediaType ) - val tabs = when (mediaType) { - MediaViewType.MOVIE -> MediaTabNavItem.MovieItems - MediaViewType.TV -> MediaTabNavItem.TvItems - else -> throw IllegalArgumentException("Media type given: ${mediaType}, \n expected one of MediaViewType.MOVIE, MediaViewType.TV") // shouldn't happen - } + val tabs = MediaTabNavItem.itemsForType(type = mediaType) val pagerState = rememberPagerState() Tabs(tabs = tabs, pagerState = pagerState) MediaTabs( @@ -61,13 +55,13 @@ fun MediaTab( } @Composable -fun MediaTabContent(appNavController: NavHostController, mediaType: MediaViewType, mediaTabItem: MediaTabNavItem) { - val viewModel: MediaTabViewModel? = when(mediaType) { - MediaViewType.MOVIE -> mediaTabItem.movieViewModel - MediaViewType.TV -> mediaTabItem.tvViewModel - else -> throw IllegalArgumentException("Media type given: ${mediaType}, \n expected one of MediaViewType.MOVIE, MediaViewType.TV") // shouldn't happen - } - val mediaListItems = viewModel?.mediaItems?.collectAsLazyPagingItems() +fun MediaTabContent( + appNavController: NavHostController, + mediaType: MediaViewType, + mediaTabItem: MediaTabNavItem +) { + val viewModel = viewModel() + val mediaListItems = viewModel.produceFlowFor(mediaType, mediaTabItem.type).collectAsLazyPagingItems() PagingPosterGrid( lazyPagingItems = mediaListItems, diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/PeopleTab.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/PeopleTab.kt index 7ba61b9..3f9e815 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/PeopleTab.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/tabs/PeopleTab.kt @@ -1,9 +1,7 @@ package com.owenlejeune.tvtime.ui.screens.tabs import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.ui.res.stringResource import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController @@ -13,7 +11,7 @@ import com.owenlejeune.tvtime.ui.components.PagingPeoplePosterGrid import com.owenlejeune.tvtime.ui.components.SearchView import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel -import com.owenlejeune.tvtime.ui.viewmodel.PeopleTabViewModel +import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.utils.types.MediaViewType @Composable @@ -30,7 +28,8 @@ fun PeopleTab( mediaType = MediaViewType.PERSON ) - val peopleList = PeopleTabViewModel().popularPeople.collectAsLazyPagingItems() + val mainViewModel = viewModel() + val peopleList = mainViewModel.popularPeople.collectAsLazyPagingItems() PagingPeoplePosterGrid( lazyPagingItems = peopleList, diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/AccountViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/AccountViewModel.kt index ae760fd..9857611 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/AccountViewModel.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/AccountViewModel.kt @@ -1,15 +1,21 @@ package com.owenlejeune.tvtime.ui.viewmodel import androidx.lifecycle.ViewModel +import androidx.paging.PagingData +import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MarkAsFavoriteBody import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchlistBody +import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.ListV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.model.DeleteListItemsBody import com.owenlejeune.tvtime.api.tmdb.api.v4.model.DeleteListItemsItem import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListUpdateBody +import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem import com.owenlejeune.tvtime.utils.SessionManager import com.owenlejeune.tvtime.utils.types.MediaViewType +import com.owenlejeune.tvtime.utils.types.ViewableMediaTypeException +import kotlinx.coroutines.flow.Flow import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -17,9 +23,94 @@ class AccountViewModel: ViewModel(), KoinComponent { private val listService: ListV4Service by inject() private val accountService: AccountService by inject() + private val accountV4Service: AccountV4Service by inject() + + private val accountId: String + get() = SessionManager.currentSession.value?.accountId ?: "" val listMap = listService.listMap + val ratedTv: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getRatedTvShows(accountId, p) }, + processor = { it.results } + ) + val favoriteTv: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getFavoriteTvShows(accountId, p) }, + processor = { it.results } + ) + val watchlistTv: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getTvShowWatchlist(accountId, p) }, + processor = { it.results } + ) + val recommendedTv: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getRecommendedTvSeries(accountId, p) }, + processor = { it.results } + ) + + val ratedMovies: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getRatedMovies(accountId, p) }, + processor = { it.results } + ) + val favoriteMovies: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getFavoriteMovies(accountId, p) }, + processor = { it.results } + ) + val watchlistMovies: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getMovieWatchlist(accountId, p) }, + processor = { it.results } + ) + val recommendedMovies: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getRecommendedMovies(accountId, p) }, + processor = { it.results } + ) + + val userLists: Flow> = createPagingFlow( + fetcher = { p -> accountV4Service.getLists(accountId, p) }, + processor = { it.results } + ) + + fun getPagingFlowFor(type: MediaViewType, accountTabType: AccountTabNavItem.AccountTabType): Flow> { + return when (accountTabType) { + AccountTabNavItem.AccountTabType.LIST -> userLists + AccountTabNavItem.AccountTabType.RATED -> { + when (type) { + MediaViewType.MOVIE -> ratedMovies + MediaViewType.TV -> ratedTv + else -> throw ViewableMediaTypeException(type) + } + } + AccountTabNavItem.AccountTabType.FAVORITE -> { + when (type) { + MediaViewType.MOVIE -> favoriteMovies + MediaViewType.TV -> favoriteTv + else -> throw ViewableMediaTypeException(type) + } + } + AccountTabNavItem.AccountTabType.WATCHLIST -> { + when (type) { + MediaViewType.MOVIE -> watchlistMovies + MediaViewType.TV -> watchlistTv + else -> throw ViewableMediaTypeException(type) + } + } + AccountTabNavItem.AccountTabType.RECOMMENDED -> { + when (type) { + MediaViewType.MOVIE -> recommendedMovies + MediaViewType.TV -> recommendedTv + else -> throw ViewableMediaTypeException(type) + } + } + } + } + + fun getRecommendedFor(type: MediaViewType): Flow> { + return when (type) { + MediaViewType.MOVIE -> recommendedMovies + MediaViewType.TV -> recommendedTv + else -> throw ViewableMediaTypeException(type) + } + } + suspend fun getList(listId: Int) { listService.getList(listId = listId) } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MainViewModel.kt index 68da0cd..ad9806f 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MainViewModel.kt @@ -1,15 +1,10 @@ package com.owenlejeune.tvtime.ui.viewmodel import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.paging.Pager -import androidx.paging.PagingConfig import androidx.paging.PagingData -import androidx.paging.cachedIn +import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService -import com.owenlejeune.tvtime.api.tmdb.api.v3.SimilarMoviesSource -import com.owenlejeune.tvtime.api.tmdb.api.v3.SimilarTvSource import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AccountStates import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CastMember @@ -23,6 +18,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Review import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Video import com.owenlejeune.tvtime.api.tmdb.api.v3.model.WatchProviders +import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem import com.owenlejeune.tvtime.utils.types.MediaViewType import com.owenlejeune.tvtime.utils.types.ViewableMediaTypeException import kotlinx.coroutines.flow.Flow @@ -48,6 +44,23 @@ class MainViewModel: ViewModel(), KoinComponent { val similarMovies = movieService.similar val movieAccountStates = movieService.accountStates + val popularMovies = createPagingFlow( + fetcher = { p -> movieService.getPopular(p) }, + processor = { it.results } + ) + val topRatedMovies = createPagingFlow( + fetcher = { p -> movieService.getTopRated(p) }, + processor = { it.results } + ) + val nowPlayingMovies = createPagingFlow( + fetcher = { p -> movieService.getNowPlaying(p) }, + processor = { it.results } + ) + val upcomingMovies = createPagingFlow( + fetcher = { p -> movieService.getUpcoming(p) }, + processor = { it.results } + ) + val detailedTv = tvService.detailTv val tvImages = tvService.images val tvCast = tvService.cast @@ -62,12 +75,34 @@ class MainViewModel: ViewModel(), KoinComponent { val similarTv = tvService.similar val tvAccountStates = tvService.accountStates + val popularTv = createPagingFlow( + fetcher = { p -> tvService.getPopular(p) }, + processor = { it.results } + ) + val topRatedTv = createPagingFlow( + fetcher = { p -> tvService.getTopRated(p) }, + processor = { it.results } + ) + val airingTodayTv = createPagingFlow( + fetcher = { p -> tvService.getNowPlaying(p) }, + processor = { it.results } + ) + val onTheAirTv = createPagingFlow( + fetcher = { p -> tvService.getUpcoming(p) }, + processor = { it.results } + ) + val peopleMap = peopleService.peopleMap val peopleCastMap = peopleService.castMap val peopleCrewMap = peopleService.crewMap val peopleImagesMap = peopleService.imagesMap val peopleExternalIdsMap = peopleService.externalIdsMap + val popularPeople = createPagingFlow( + fetcher = { p -> peopleService.getPopular(p) }, + processor = { it.results } + ) + private fun providesForType(type: MediaViewType, movies: () -> T, tv: () -> T): T { return when (type) { MediaViewType.MOVIE -> movies() @@ -120,6 +155,28 @@ class MainViewModel: ViewModel(), KoinComponent { return providesForType(type, { movieAccountStates }, { tvAccountStates} ) } + fun produceFlowFor(mediaType: MediaViewType, contentType: MediaTabNavItem.Type): Flow> { + return providesForType( + mediaType, + { + when (contentType) { + MediaTabNavItem.Type.UPCOMING -> upcomingMovies + MediaTabNavItem.Type.TOP_RATED -> topRatedMovies + MediaTabNavItem.Type.NOW_PLAYING -> nowPlayingMovies + MediaTabNavItem.Type.POPULAR -> popularMovies + } + }, + { + when (contentType) { + MediaTabNavItem.Type.UPCOMING -> onTheAirTv + MediaTabNavItem.Type.TOP_RATED -> topRatedTv + MediaTabNavItem.Type.NOW_PLAYING -> airingTodayTv + MediaTabNavItem.Type.POPULAR -> popularTv + } + } + ) + } + suspend fun getById(id: Int, type: MediaViewType) { when (type) { MediaViewType.MOVIE -> movieService.getById(id) @@ -215,14 +272,16 @@ class MainViewModel: ViewModel(), KoinComponent { fun getSimilar(id: Int, type: MediaViewType) { when (type) { MediaViewType.MOVIE -> { - similarMovies[id] = Pager(PagingConfig(pageSize = 1)) { - SimilarMoviesSource(id) - }.flow.cachedIn(viewModelScope) + similarMovies[id] = createPagingFlow( + fetcher = { p -> movieService.getSimilar(id, p) }, + processor = { it.results } + ) } MediaViewType.TV -> { - similarTv[id] = Pager(PagingConfig(pageSize = 1)) { - SimilarTvSource(id) - }.flow.cachedIn(viewModelScope) + similarTv[id] = createPagingFlow( + fetcher = { p -> tvService.getSimilar(id, p) }, + processor = { it.results } + ) } else -> {} } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MediaTabViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MediaTabViewModel.kt deleted file mode 100644 index 4e0b409..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/MediaTabViewModel.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.owenlejeune.tvtime.ui.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.paging.Pager -import androidx.paging.PagingConfig -import androidx.paging.PagingData -import androidx.paging.cachedIn -import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService -import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService -import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePagingSource -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem -import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun -import kotlinx.coroutines.flow.Flow -import org.koin.core.component.KoinComponent -import org.koin.java.KoinJavaComponent.get - -sealed class MediaTabViewModel(service: HomePageService, mediaFetchFun: MediaFetchFun, tag: String): ViewModel(), KoinComponent { - - val mediaItems: Flow> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) { - HomePagePagingSource(service = service, mediaFetch = mediaFetchFun, tag = tag) - }.flow.cachedIn(viewModelScope) - - object PopularMoviesVM: MediaTabViewModel(get(MoviesService::class.java), { s, p -> s.getPopular(p) }, PopularMoviesVM::class.java.simpleName) - object TopRatedMoviesVM: MediaTabViewModel(get(MoviesService::class.java), { s, p -> s.getTopRated(p) }, TopRatedMoviesVM::class.java.simpleName) - object NowPlayingMoviesVM: MediaTabViewModel(get(MoviesService::class.java), { s, p -> s.getNowPlaying(p) }, NowPlayingMoviesVM::class.java.simpleName) - object UpcomingMoviesVM: MediaTabViewModel(get(MoviesService::class.java), { s, p -> s.getUpcoming(p) }, UpcomingMoviesVM::class.java.simpleName) - object PopularTvVM: MediaTabViewModel(get(TvService::class.java), { s, p -> s.getPopular(p) }, PopularTvVM::class.java.simpleName) - object TopRatedTvVM: MediaTabViewModel(get(TvService::class.java), { s, p -> s.getTopRated(p) }, TopRatedTvVM::class.java.simpleName) - object AiringTodayTvVM: MediaTabViewModel(get(TvService::class.java), { s, p -> s.getNowPlaying(p) }, AiringTodayTvVM::class.java.simpleName) - object OnTheAirTvVM: MediaTabViewModel(get(TvService::class.java), { s, p -> s.getUpcoming(p) }, OnTheAirTvVM::class.java.simpleName) - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/PeopleTabViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/PeopleTabViewModel.kt deleted file mode 100644 index 01e6bf8..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/PeopleTabViewModel.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.owenlejeune.tvtime.ui.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.paging.Pager -import androidx.paging.PagingConfig -import androidx.paging.PagingData -import androidx.paging.cachedIn -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePeoplePagingSource -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePerson -import kotlinx.coroutines.flow.Flow - -class PeopleTabViewModel: ViewModel() { - - val popularPeople: Flow> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) { - HomePagePeoplePagingSource() - }.flow.cachedIn(viewModelScope) - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/RecommendedMediaViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/RecommendedMediaViewModel.kt deleted file mode 100644 index e73adf0..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/RecommendedMediaViewModel.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.owenlejeune.tvtime.ui.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.paging.Pager -import androidx.paging.PagingConfig -import androidx.paging.PagingData -import androidx.paging.cachedIn -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RecommendedMediaPagingSource -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem -import com.owenlejeune.tvtime.utils.types.MediaViewType -import kotlinx.coroutines.flow.Flow -import org.koin.core.component.KoinComponent - -sealed class RecommendedMediaViewModel(mediaType: MediaViewType): ViewModel(), KoinComponent { - - val mediaItems: Flow> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) { - RecommendedMediaPagingSource(mediaType) - }.flow.cachedIn(viewModelScope) - - object RecommendedMoviesVM: RecommendedMediaViewModel(MediaViewType.MOVIE) - object RecommendedTvVM: RecommendedMediaViewModel(MediaViewType.TV) - -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SearchViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SearchViewModel.kt index bc911b0..940094e 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SearchViewModel.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SearchViewModel.kt @@ -1,22 +1,12 @@ package com.owenlejeune.tvtime.ui.viewmodel -import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.paging.Pager -import androidx.paging.PagingConfig import androidx.paging.PagingData -import androidx.paging.cachedIn -import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchPagingSource +import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchResultProvider import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchService -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SearchResultMovie -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SearchResultPerson -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SearchResultTv import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Searchable -import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SortableSearchResult import com.owenlejeune.tvtime.utils.types.MediaViewType -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -48,23 +38,26 @@ class SearchViewModel: ViewModel(), KoinComponent { } fun searchForMovies(query: String) { - movieResults.value = createPagingSource(viewModelScope) { service.searchMovies(query, it) } + movieResults.value = createPagingSource { service.searchMovies(query, it) } } fun searchForTv(query: String) { - tvResults.value = createPagingSource(viewModelScope) { service.searchTv(query, it) } + tvResults.value = createPagingSource { service.searchTv(query, it) } } fun searchForPeople(query: String) { - peopleResults.value = createPagingSource(viewModelScope) { service.searchPeople(query, it) } + peopleResults.value = createPagingSource { service.searchPeople(query, it) } } fun searchMulti(query: String) { - multiResults.value = createPagingSource(viewModelScope) { service.searchMulti(query, it) } + multiResults.value = createPagingSource { service.searchMulti(query, it) } } - private fun createPagingSource(viewModelScope: CoroutineScope, provideResults: SearchResultProvider): Flow> { - return Pager(PagingConfig(pageSize = 1)) { SearchPagingSource(provideResults) }.flow.cachedIn(viewModelScope) + private fun createPagingSource(provideResults: SearchResultProvider): Flow> { + return createPagingFlow( + fetcher = { provideResults(it) }, + processor = { it.results } + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ViewModelConstants.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ViewModelConstants.kt index 812eed7..d8fbcd8 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ViewModelConstants.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ViewModelConstants.kt @@ -2,6 +2,6 @@ package com.owenlejeune.tvtime.ui.viewmodel object ViewModelConstants { - const val PAGING_SIZE = 6 + const val PAGING_SIZE = 3 } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt b/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt index db7f0b8..1255016 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt @@ -2,22 +2,17 @@ package com.owenlejeune.tvtime.utils import android.content.Context import android.widget.Toast -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import com.google.gson.annotations.SerializedName import com.owenlejeune.tvtime.R -import com.owenlejeune.tvtime.api.tmdb.TmdbClient import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService import com.owenlejeune.tvtime.api.tmdb.api.v3.AuthenticationService import com.owenlejeune.tvtime.api.tmdb.api.v3.model.* -import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.AuthenticationV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AuthAccessBody import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AuthDeleteBody import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AuthRequestBody -import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AccountList import com.owenlejeune.tvtime.preferences.AppPreferences -import com.owenlejeune.tvtime.utils.types.MediaViewType import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -133,76 +128,10 @@ object SessionManager: KoinComponent { abstract class Session(val sessionId: String, val isAuthorized: Boolean, val accessToken: String = "", val accountId: String = "") { - val ratedMovies = mutableStateListOf() - val ratedTvShows = mutableStateListOf() - val ratedTvEpisodes = mutableStateListOf() val accountDetails = mutableStateOf(null) - val accountLists = mutableStateListOf() - val favoriteMovies = mutableStateListOf() - val favoriteTvShows = mutableStateListOf() - val movieWatchlist = mutableStateListOf() - val tvWatchlist = mutableStateListOf() - - fun hasRatedMovie(id: Int): Boolean { - return ratedMovies.map { it.id }.contains(id) - } - - fun hasRatedTvShow(id: Int): Boolean { - return ratedTvShows.map { it.id }.contains(id) - } - - fun hasRatedTvEpisode(id: Int): Boolean { - return ratedTvEpisodes.map { it.id }.contains(id) - } - - fun getRatingForId(id: Int, type: MediaViewType): Float? { - return when(type) { - MediaViewType.MOVIE -> ratedMovies.firstOrNull { it.id == id }?.rating - MediaViewType.TV -> ratedTvShows.firstOrNull { it.id == id }?.rating - MediaViewType.EPISODE -> ratedTvEpisodes.firstOrNull { it.id == id }?.rating - else -> null - } - } - - fun hasFavoritedMovie(id: Int): Boolean { - return favoriteMovies.map { it.id }.contains(id) - } - - fun hasFavoritedTvShow(id: Int): Boolean { - return favoriteTvShows.map { it.id }.contains(id) - } - - fun hasWatchlistedMovie(id: Int): Boolean { - return movieWatchlist.map { it.id }.contains(id) - } - - fun hasWatchlistedTvShow(id: Int): Boolean { - return tvWatchlist.map { it.id }.contains(id) - } abstract suspend fun initialize() - abstract suspend fun refresh(changed: Array = Changed.All) - - enum class Changed { - AccountDetails, - Lists, - RatedMovies, - RatedTv, - RatedEpisodes, - FavoriteMovies, - FavoriteTv, - WatchlistMovies, - WatchlistTv; - - companion object { - val All get() = values() - val Rated get() = arrayOf(RatedMovies, RatedTv, RatedEpisodes) - val Favorites get() = arrayOf(FavoriteMovies, FavoriteTv) - val Watchlist get() = arrayOf(WatchlistMovies, WatchlistTv) - val List get() = arrayOf(Lists) - } - } } private class InProgressSession(requestToken: String): Session(requestToken, false) { @@ -210,10 +139,6 @@ object SessionManager: KoinComponent { // do nothing } - override suspend fun refresh(changed: Array) { - // do nothing - } - } private class AuthorizedSession( @@ -222,122 +147,11 @@ object SessionManager: KoinComponent { accountId: String = "" ): Session(sessionId, true, accessToken, accountId) { private val service: AccountService by inject() - private val serviceV4: AccountV4Service by inject() override suspend fun initialize() { - refresh() - } - - override suspend fun refresh(changed: Array) { - if (changed.contains(Changed.AccountDetails)) { - val response = service.getAccountDetails() - if (response.isSuccessful) { - accountDetails.value = response.body() - accountDetails.value?.let { - refreshWithAccountId(it.id, changed) - } - } - } else if (accountDetails.value != null) { - refreshWithAccountId(accountDetails.value!!.id, changed) - } - } - - private suspend fun refreshWithAccountId(accountId: Int, changed: Array = Changed.All) { - if (changed.contains(Changed.Lists)) { - serviceV4.getLists(preferences.authorizedSessionValues?.accountId ?: "").apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - accountLists.clear() - accountLists.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.FavoriteMovies)) { - service.getFavoriteMovies(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - favoriteMovies.clear() - favoriteMovies.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.FavoriteTv)) { - service.getFavoriteTvShows(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - favoriteTvShows.clear() - favoriteTvShows.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.RatedMovies)) { - service.getRatedMovies(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - ratedMovies.clear() - ratedMovies.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.RatedTv)) { - service.getRatedTvShows(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - ratedTvShows.clear() - ratedTvShows.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.RatedEpisodes)) { - service.getRatedTvEpisodes(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - ratedTvEpisodes.clear() - ratedTvEpisodes.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.WatchlistMovies)) { - service.getMovieWatchlist(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - movieWatchlist.clear() - movieWatchlist.addAll(it) - } - } - } - } - } - if (changed.contains(Changed.WatchlistTv)) { - service.getTvWatchlist(accountId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - body()?.results?.let { - tvWatchlist.clear() - tvWatchlist.addAll(it) - } - } - } - } + val response = service.getAccountDetails() + if (response.isSuccessful) { + accountDetails.value = response.body() } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bd748c3..bae9dc5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -94,6 +94,7 @@ Search Icon Add a Rating + My Rating Submit rating Delete rating