add in infrastructure for authorized session account tab lists

This commit is contained in:
Owen LeJeune
2022-03-10 14:58:13 -05:00
parent 0b5e3ee053
commit 695af865ec
4 changed files with 164 additions and 64 deletions

View File

@@ -695,7 +695,7 @@ fun RoundedLetterImage(
topPadding: Dp = size / 5
) {
Box(
modifier = Modifier
modifier = modifier
.clip(CircleShape)
.size(size)
.background(color = MaterialTheme.colorScheme.tertiary)

View File

@@ -3,31 +3,38 @@ package com.owenlejeune.tvtime.ui.navigation
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.model.RatedMedia
import com.owenlejeune.tvtime.api.tmdb.model.*
import com.owenlejeune.tvtime.ui.screens.MediaViewType
import com.owenlejeune.tvtime.ui.screens.tabs.bottom.AccountTabContent
import com.owenlejeune.tvtime.utils.ResourceUtils
import com.owenlejeune.tvtime.utils.SessionManager
import org.koin.core.component.inject
import kotlin.reflect.KClass
sealed class AccountTabNavItem(stringRes: Int, route: String, val mediaType: MediaViewType, val screen: AccountNavComposableFun, val listFetchFun: ListFetchFun): TabNavItem(route) {
sealed class AccountTabNavItem(stringRes: Int, route: String, val mediaType: MediaViewType, val screen: AccountNavComposableFun, val listFetchFun: ListFetchFun, val listType: KClass<*>): TabNavItem(route) {
private val resourceUtils: ResourceUtils by inject()
override val name = resourceUtils.getString(stringRes)
companion object {
val GuestItems = listOf(RatedMovies, RatedTvShows, RatedTvEpisodes)
val AuthorizedItems = listOf(RatedMovies, RatedTvShows, RatedTvEpisodes, FavoriteMovies, FavoriteTvShows, MovieWatchlist, TvWatchlist)
}
object RatedMovies: AccountTabNavItem(R.string.nav_rated_movies_title, "rated_movies_route", MediaViewType.MOVIE, screenContent, { SessionManager.currentSession?.ratedMovies ?: emptyList() } )
object RatedTvShows: AccountTabNavItem(R.string.nav_rated_shows_title, "rated_shows_route", MediaViewType.TV, screenContent, { SessionManager.currentSession?.ratedTvShows ?: emptyList() } )
object RatedTvEpisodes: AccountTabNavItem(R.string.nav_rated_episodes_title, "rated_episodes_route", MediaViewType.EPISODE, screenContent, { SessionManager.currentSession?.ratedTvEpisodes ?: emptyList() } )
object RatedMovies: AccountTabNavItem(R.string.nav_rated_movies_title, "rated_movies_route", MediaViewType.MOVIE, screenContent, { SessionManager.currentSession?.ratedMovies ?: emptyList() }, RatedMovie::class)
object RatedTvShows: AccountTabNavItem(R.string.nav_rated_shows_title, "rated_shows_route", MediaViewType.TV, screenContent, { SessionManager.currentSession?.ratedTvShows ?: emptyList() }, RatedTv::class)
object RatedTvEpisodes: AccountTabNavItem(R.string.nav_rated_episodes_title, "rated_episodes_route", MediaViewType.EPISODE, screenContent, { SessionManager.currentSession?.ratedTvEpisodes ?: emptyList() }, RatedEpisode::class)
// object Lists
object FavoriteMovies: AccountTabNavItem(R.string.nav_favorite_movies_title, "favorite_movies_route", MediaViewType.MOVIE, screenContent, { SessionManager.currentSession?.favoriteMovies ?: emptyList() }, FavoriteMovie::class)
object FavoriteTvShows: AccountTabNavItem(R.string.nav_favorite_tv_show_title, "favorite_shows_route", MediaViewType.TV, screenContent, { SessionManager.currentSession?.favoriteMovies ?: emptyList() }, FavoriteTvSeries::class)
object MovieWatchlist: AccountTabNavItem(R.string.nav_movie_watchlist_title, "movie_watchlist_route", MediaViewType.MOVIE, screenContent, { SessionManager.currentSession?.movieWatchlist ?: emptyList() }, WatchlistMovie::class)
object TvWatchlist: AccountTabNavItem(R.string.nav_tv_watchlist_title, "tv_watchlist_route", MediaViewType.TV, screenContent, { SessionManager.currentSession?.tvWatchlist ?: emptyList() }, WatchlistTvSeries::class)
}
private val screenContent: AccountNavComposableFun = { appNavController, mediaViewType, listFetchFun ->
AccountTabContent(appNavController = appNavController, mediaViewType = mediaViewType, listFetchFun = listFetchFun)
private val screenContent: AccountNavComposableFun = { appNavController, mediaViewType, listFetchFun, clazz ->
AccountTabContent(appNavController = appNavController, mediaViewType = mediaViewType, listFetchFun = listFetchFun, clazz = clazz)
}
typealias ListFetchFun = () -> List<RatedMedia>
typealias ListFetchFun = () -> List<Any>
typealias AccountNavComposableFun = @Composable (NavHostController, MediaViewType, ListFetchFun) -> Unit
typealias AccountNavComposableFun = @Composable (NavHostController, MediaViewType, ListFetchFun, KClass<*>) -> Unit

View File

@@ -25,21 +25,20 @@ import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.model.RatedMovie
import com.owenlejeune.tvtime.api.tmdb.model.RatedTopLevelMedia
import com.owenlejeune.tvtime.api.tmdb.model.RatedTv
import com.owenlejeune.tvtime.api.tmdb.model.*
import com.owenlejeune.tvtime.ui.components.*
import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem
import com.owenlejeune.tvtime.ui.navigation.ListFetchFun
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
import com.owenlejeune.tvtime.ui.screens.MediaViewType
import com.owenlejeune.tvtime.ui.screens.tabs.top.Tabs
import com.owenlejeune.tvtime.ui.screens.tabs.top.ScrollableTabs
import com.owenlejeune.tvtime.utils.SessionManager
import com.owenlejeune.tvtime.utils.TmdbUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.reflect.KClass
private const val GUEST_SIGN_IN = "guest_sign_in"
private const val SIGN_OUT = "sign_out"
@@ -69,14 +68,14 @@ fun AccountTab(
if (lastSelectedOption.value.isNotBlank() || lastSelectedOption.value.isBlank()) {
SessionManager.currentSession?.let { session ->
val tabs = if (session.isAuthorized) {
AccountTabNavItem.GuestItems
AccountTabNavItem.AuthorizedItems
} else {
AccountTabNavItem.GuestItems
}
Column {
val pagerState = rememberPagerState()
Tabs(tabs = tabs, pagerState = pagerState)
ScrollableTabs(tabs = tabs, pagerState = pagerState)
AccountTabs(
appNavController = appNavController,
tabs = tabs,
@@ -88,10 +87,11 @@ fun AccountTab(
}
@Composable
fun AccountTabContent(
fun <T: Any> AccountTabContent(
appNavController: NavHostController,
mediaViewType: MediaViewType,
listFetchFun: ListFetchFun
listFetchFun: ListFetchFun,
clazz: KClass<T>
) {
val contentItems = listFetchFun()
@@ -112,51 +112,85 @@ fun AccountTabContent(
}
} else {
items(contentItems.size) { i ->
val ratedItem = contentItems[i] as RatedTopLevelMedia
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.clickable(
onClick = {
appNavController.navigate(
"${MainNavItem.DetailView.route}/${mediaViewType}/${ratedItem.id}"
)
}
)
) {
Image(
modifier = Modifier
.width(60.dp)
.height(80.dp),
painter = rememberImagePainter(
data = TmdbUtils.getFullPosterPath(ratedItem.posterPath)
),
contentDescription = ""
)
Column(
modifier = Modifier.height(80.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
Text(
text = ratedItem.name,
color = MaterialTheme.colorScheme.onBackground,
fontSize = 18.sp
when (clazz) {
RatedMovie::class -> {
val item = contentItems[i] as RatedMovie
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.name,
date = item.releaseDate,
rating = item.rating
)
val date = when (ratedItem) {
is RatedMovie -> ratedItem.releaseDate
is RatedTv -> ratedItem.firstAirDate
else -> ""
}
Text(
text = date,
color = MaterialTheme.colorScheme.onBackground
}
RatedTv::class -> {
val item = contentItems[i] as RatedTv
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.name,
date = item.firstAirDate,
rating = item.rating
)
Text(
text = stringResource(id = R.string.rating_test, (ratedItem.rating * 10).toInt()),
color = MaterialTheme.colorScheme.onBackground
}
RatedEpisode::class -> {
val item = contentItems[i] as RatedEpisode
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = null,
name = item.name,
date = item.airDate,
rating = item.rating
)
}
FavoriteMovie::class -> {
val item = contentItems[i] as FavoriteMovie
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.title,
date = item.releaseDate
)
}
FavoriteTvSeries::class -> {
val item = contentItems[i] as FavoriteTvSeries
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.title,
date = item.releaseDate
)
}
WatchlistMovie::class -> {
val item = contentItems[i] as WatchlistMovie
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.title,
date = item.releaseDate
)
}
WatchlistTvSeries::class -> {
val item = contentItems[i] as WatchlistTvSeries
MediaItemRow(
appNavController = appNavController,
mediaViewType = mediaViewType,
id = item.id,
posterPath = TmdbUtils.getFullPosterPath(item.posterPath),
name = item.title,
date = item.releaseDate
)
}
}
@@ -165,6 +199,61 @@ fun AccountTabContent(
}
}
@Composable
private fun MediaItemRow(
appNavController: NavHostController,
mediaViewType: MediaViewType,
id: Int,
posterPath: String?,
name: String,
date: String,
rating: Float? = null
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.clickable(
onClick = {
appNavController.navigate(
"${MainNavItem.DetailView.route}/${mediaViewType}/${id}"
)
}
)
) {
Image(
modifier = Modifier
.width(60.dp)
.height(80.dp),
painter = rememberImagePainter(
data = posterPath
),
contentDescription = ""
)
Column(
modifier = Modifier.height(80.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
Text(
text = name,
color = MaterialTheme.colorScheme.onBackground,
fontSize = 18.sp
)
Text(
text = date,
color = MaterialTheme.colorScheme.onBackground
)
if (rating != null) {
Text(
text = stringResource(id = R.string.rating_test, (rating * 10).toInt()),
color = MaterialTheme.colorScheme.onBackground
)
}
}
}
}
@Composable
private fun AccountDropdownMenu(
session: SessionManager.Session?,
@@ -266,7 +355,7 @@ private fun GuestSessionMenuItems(
@Composable
private fun GuestSessionIcon() {
val guestName = stringResource(id = R.string.account_name_guest)
RoundedLetterImage(size = 40.dp, character = guestName[0], modifier = Modifier.padding(end = 8.dp), topPadding = 40.dp / 8)
RoundedLetterImage(size = 40.dp, character = guestName[0], topPadding = 40.dp / 8)
}
@Composable
@@ -311,6 +400,6 @@ fun AccountTabs(
appNavController: NavHostController
) {
HorizontalPager(count = tabs.size, state = pagerState) { page ->
tabs[page].screen(appNavController, tabs[page].mediaType, tabs[page].listFetchFun)
tabs[page].screen(appNavController, tabs[page].mediaType, tabs[page].listFetchFun, tabs[page].listType)
}
}

View File

@@ -18,6 +18,10 @@
<string name="nav_rated_episodes_title">Rated TV Episodes</string>
<string name="nav_people_title">People</string>
<string name="nav_popular_people_title">Popular People</string>
<string name="nav_favorite_movies_title">Favorite Movies</string>
<string name="nav_favorite_tv_show_title">Favorite TV Shows</string>
<string name="nav_movie_watchlist_title">Movie Watchlist</string>
<string name="nav_tv_watchlist_title">TV Watchlist</string>
<!-- Headings -->
<string name="cast_label">Cast</string>
@@ -84,7 +88,7 @@
<string name="account_not_logged_in">Not logged in</string>
<string name="no_rated_content_message">No rated content</string>
<string name="rating_test">Rating: $1%d</string>
<string name="rating_test">Rating: %1$d</string>
<string name="action_sign_in_as_guest">Sign In as Guest</string>
<string name="account_menu_content_description">Account Menu</string>
<string name="action_sign_out">Sign Out</string>