fix up some season loading stuff

This commit is contained in:
Owen LeJeune
2023-07-30 22:11:33 -04:00
parent 084a22dd7f
commit 314e4ca964
6 changed files with 88 additions and 18 deletions

View File

@@ -64,7 +64,7 @@ interface MoviesApi {
suspend fun getExternalIds(@Path("id") id: Int): Response<ExternalIds>
@GET("movie/{id}/account_states")
suspend fun getAccountStates(@Path("id") id: Int, @Query("session_id") sessionId: String): Response<AccountStates>
suspend fun getAccountStates(@Path("id") id: Int): Response<AccountStates>
@GET("discover/movie")
suspend fun discover(@Query("with_keywords") keywords: String? = null, @Query("page") page: Int): Response<SearchResult<SearchResultMovie>>

View File

@@ -148,9 +148,8 @@ class MoviesService: KoinComponent, DetailService, HomePageService {
}
override suspend fun getAccountStates(id: Int) {
val sessionId = SessionManager.currentSession.value?.sessionId ?: throw Exception("Session must not be null")
loadRemoteData(
{ movieService.getAccountStates(id, sessionId) },
{ movieService.getAccountStates(id) },
{ accountStates[id] = it },
accountStatesLoadingState,
false

View File

@@ -145,7 +145,9 @@ private fun fetchData(
scope.launch { mainViewModel.getVideos(itemId, type, force) }
scope.launch { mainViewModel.getWatchProviders(itemId, type, force) }
scope.launch { mainViewModel.getReviews(itemId, type, force) }
scope.launch { mainViewModel.getAccountStates(itemId, type) }
if (SessionManager.isLoggedIn) {
scope.launch { mainViewModel.getAccountStates(itemId, type) }
}
when (type) {
MediaViewType.MOVIE -> {
@@ -190,6 +192,9 @@ fun MediaDetailScreen(
if (type == MediaViewType.TV) {
LaunchedEffect(mediaItem) {
val lastSeason = (mediaItem as DetailedTv?)?.numberOfSeasons ?: 0
// for (i in lastSeason downTo 0) {
// mainViewModel.getSeason(itemId, i)
// }
if (lastSeason > 0) {
mainViewModel.getSeason(itemId, lastSeason)
}
@@ -871,7 +876,7 @@ private fun SeasonCard(
appNavController: NavController
) {
val seasonsMap = remember { mainViewModel.tvSeasons }
val lastSeason = seasonsMap[itemId]?.lastOrNull()
val lastSeason = seasonsMap[itemId]?.maxByOrNull { it.seasonNumber }
lastSeason?.let {
ContentCard(

View File

@@ -1,6 +1,11 @@
package com.owenlejeune.tvtime.ui.screens
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -9,17 +14,26 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -29,6 +43,7 @@ import com.google.accompanist.pager.ExperimentalPagerApi
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Episode
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Season
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SeasonAccountStates
import com.owenlejeune.tvtime.extensions.toCompositeParts
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.CastCrewCard
@@ -42,6 +57,7 @@ import com.owenlejeune.tvtime.ui.components.WatchProvidersCard
import com.owenlejeune.tvtime.ui.theme.Typography
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.SessionManager
import com.owenlejeune.tvtime.utils.TmdbUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -55,7 +71,9 @@ private fun fetchData(
) {
val scope = CoroutineScope(Dispatchers.IO)
scope.launch { mainViewModel.getSeason(seriesId, seasonNumber, force) }
scope.launch { mainViewModel.getSeasonAccountStates(seriesId, seasonNumber, force) }
if (SessionManager.isLoggedIn) {
scope.launch { mainViewModel.getSeasonAccountStates(seriesId, seasonNumber, force) }
}
scope.launch { mainViewModel.getSeasonImages(seriesId, seasonNumber, force) }
scope.launch { mainViewModel.getSeasonVideos(seriesId, seasonNumber, force) }
scope.launch { mainViewModel.getSeasonCredits(seriesId, seasonNumber, force) }
@@ -126,26 +144,61 @@ private fun SeasonContent(
expandedPosterAsBackdrop = true
)
var isExpanded by remember { mutableStateOf(true) }
Column(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = season.name,
color = MaterialTheme.colorScheme.secondary,
style = Typography.headlineLarge,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.fillMaxWidth()
)
Row {
Text(
text = season.name,
color = MaterialTheme.colorScheme.secondary,
style = Typography.headlineLarge,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.weight(1f))
var currentRotation by remember { mutableFloatStateOf(180f) }
val rotation = remember { Animatable(currentRotation) }
LaunchedEffect(isExpanded) {
rotation.animateTo(
targetValue = if (isExpanded) 180f else 0f,
animationSpec = tween(200, easing = LinearEasing)
) {
currentRotation = value
}
}
Icon(
imageVector = Icons.Outlined.ExpandMore,
contentDescription = null,
modifier = Modifier
.size(48.dp)
.rotate(currentRotation)
.clickable {
isExpanded = !isExpanded
},
tint = MaterialTheme.colorScheme.onSurface,
)
}
val accountStatesMap = remember { mainViewModel.tvSeasonAccountStates }
val accountStates = accountStatesMap[seriesId]?.get(season.seasonNumber)
season.episodes.forEach { episode ->
val rating = accountStates?.results?.find { it.id == episode.id }?.takeUnless { !it.isRated }?.rating
SeasonEpisodeItem(appNavController = appNavController, episode = episode, rating = rating)
AnimatedVisibility(
visible = isExpanded
) {
Column(
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
season.episodes.forEach { episode ->
DrawEpisodeCard(
episode = episode,
accountStates = accountStates,
appNavController = appNavController
)
}
}
}
val imagesMap = remember { mainViewModel.tvSeasonImages }
@@ -173,6 +226,16 @@ private fun SeasonContent(
}
}
@Composable
private fun DrawEpisodeCard(
episode: Episode,
accountStates: SeasonAccountStates?,
appNavController: NavController
) {
val rating = accountStates?.results?.find { it.id == episode.id }?.takeUnless { !it.isRated }?.rating
SeasonEpisodeItem(appNavController = appNavController, episode = episode, rating = rating)
}
@Composable
private fun SeasonEpisodeItem(
appNavController: NavController,

View File

@@ -102,7 +102,7 @@ fun SeasonListScreen(
appNavController = appNavController,
seriesId = id,
season = season,
expandedByDefault = index == 0
expandedByDefault = index == 1
)
}

View File

@@ -29,6 +29,9 @@ object SessionManager: KoinComponent {
val currentSession = mutableStateOf<Session?>(null)
val isLoggedIn: Boolean
get() = currentSession.value?.isAuthorized == true
class AuthorizedSessionValues(
@SerializedName("session_id") val sessionId: String,
@SerializedName("access_token") val accessToken: String,