mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-08 12:42:44 -05:00
refactor navigation
This commit is contained in:
@@ -1,59 +1,25 @@
|
||||
package com.owenlejeune.tvtime
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import androidx.navigation.navDeepLink
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.kieronquinn.monetcompat.app.MonetCompatActivity
|
||||
import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
||||
import com.owenlejeune.tvtime.extensions.navigateInBottomBar
|
||||
import com.owenlejeune.tvtime.extensions.rememberWindowSizeClass
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.AccountIcon
|
||||
import com.owenlejeune.tvtime.ui.components.ProfileMenuContainer
|
||||
import com.owenlejeune.tvtime.ui.components.ProfileMenuDefaults
|
||||
import com.owenlejeune.tvtime.ui.components.ProfileMenuOverlay
|
||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavGraph
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.SearchScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.main.*
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavigationHost
|
||||
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavItem
|
||||
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
|
||||
import com.owenlejeune.tvtime.utils.KeyboardManager
|
||||
import com.owenlejeune.tvtime.utils.NavConstants
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
class MainActivity : MonetCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -63,7 +29,7 @@ class MainActivity : MonetCompatActivity() {
|
||||
SessionManager.initialize()
|
||||
}
|
||||
|
||||
val mainNavStartRoute = BottomNavItem.SortedItems[0].route
|
||||
val mainNavStartRoute = HomeScreenNavItem.SortedItems[0].route
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
monet.awaitMonetReady()
|
||||
@@ -73,7 +39,7 @@ class MainActivity : MonetCompatActivity() {
|
||||
val windowSize = rememberWindowSizeClass()
|
||||
val appNavController = rememberNavController()
|
||||
Box {
|
||||
MainNavigationRoutes(
|
||||
AppNavigationHost(
|
||||
appNavController = appNavController,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
windowSize = windowSize
|
||||
@@ -84,394 +50,6 @@ class MainActivity : MonetCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppScaffold(
|
||||
appNavController: NavHostController,
|
||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route,
|
||||
windowSize: WindowSizeClass,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||
val scrollBehavior = remember(decayAnimationSpec) {
|
||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||
}
|
||||
|
||||
val appBarTitle = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||
val appBarActions = remember { mutableStateOf<@Composable RowScope.() -> Unit>({}) }
|
||||
val fab = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||
|
||||
val showProfileMenuOverlay = remember { mutableStateOf(false) }
|
||||
val navigationIcon = @Composable {
|
||||
AccountIcon(
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
size = 32.dp,
|
||||
onClick = { showProfileMenuOverlay.value = true }
|
||||
)
|
||||
}
|
||||
|
||||
val defaultNavBarColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.08f).compositeOver(background = MaterialTheme.colorScheme.surface)
|
||||
|
||||
ProfileMenuContainer(
|
||||
appNavController = appNavController,
|
||||
visible = showProfileMenuOverlay.value,
|
||||
onDismissRequest = { showProfileMenuOverlay.value = false },
|
||||
colors = ProfileMenuDefaults.systemBarColors(navBarColor = defaultNavBarColor)
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
TopBar(
|
||||
appNavController = appNavController,
|
||||
title = appBarTitle.value,
|
||||
scrollBehavior = scrollBehavior,
|
||||
appBarActions = appBarActions,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
fab.value()
|
||||
},
|
||||
bottomBar = {
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
BottomNavBar(navController = navController)
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
MainContent(
|
||||
windowSize = windowSize,
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
topBarScrollBehaviour = scrollBehavior,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
appNavController: NavHostController,
|
||||
title: @Composable () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {}
|
||||
) {
|
||||
LargeTopAppBar(
|
||||
title = title,
|
||||
scrollBehavior = scrollBehavior,
|
||||
colors = TopAppBarDefaults
|
||||
.largeTopAppBarColors(
|
||||
scrolledContainerColor = MaterialTheme.colorScheme.background
|
||||
),
|
||||
actions = {
|
||||
appBarActions.value(this)
|
||||
},
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomNavBar(
|
||||
navController: NavController,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
|
||||
NavigationBar {
|
||||
BottomNavItem.SortedItems.forEach { item ->
|
||||
val isSelected = currentRoute == item.route
|
||||
NavigationBarItem(
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.clip(RoundedCornerShape(24.dp)),
|
||||
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
||||
label = {
|
||||
val name = if (preferences.showBottomTabLabels) item.name else " "
|
||||
Text(text = name)
|
||||
},
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
if (!isSelected) {
|
||||
navController.navigateInBottomBar(item.route)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainContent(
|
||||
windowSize: WindowSizeClass,
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||
) {
|
||||
if (windowSize == WindowSizeClass.Expanded) {
|
||||
DualColumnMainContent(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
topBarScrollBehaviour = topBarScrollBehaviour,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
} else {
|
||||
SingleColumnMainContent(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleColumnMainContent(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||
) {
|
||||
MainMediaView(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DualColumnMainContent(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
|
||||
Row(modifier = Modifier.fillMaxSize()) {
|
||||
NavigationRail {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
BottomNavItem.SortedItems.forEachIndexed { index, item ->
|
||||
val isSelected = currentRoute == item.route
|
||||
NavigationRailItem(
|
||||
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
||||
label = { if (preferences.showBottomTabLabels) Text(item.name) },
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
if (!isSelected) {
|
||||
navController.navigateInBottomBar(item.route)
|
||||
}
|
||||
}
|
||||
)
|
||||
if (index < BottomNavItem.SortedItems.size - 1) {
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
Column {
|
||||
TopBar(
|
||||
appNavController = appNavController,
|
||||
title = appBarTitle.value,
|
||||
scrollBehavior = topBarScrollBehaviour,
|
||||
appBarActions = appBarActions,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
MainMediaView(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainMediaView(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<RowScope.() -> Unit> = mutableStateOf({}),
|
||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||
) {
|
||||
Column {
|
||||
BackHandler(enabled = true) {
|
||||
finish()
|
||||
}
|
||||
|
||||
MainNavGraph(
|
||||
activity = this@MainActivity,
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
startDestination = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainNavigationRoutes(
|
||||
startDestination: String = MainNavItem.MainView.route,
|
||||
mainNavStartRoute: String = MainNavItem.Items[0].route,
|
||||
appNavController: NavHostController,
|
||||
windowSize: WindowSizeClass,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
NavHost(navController = appNavController, startDestination = startDestination) {
|
||||
composable(MainNavItem.MainView.route) {
|
||||
AppScaffold(
|
||||
appNavController = appNavController,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
composable(
|
||||
MainNavItem.DetailView.route.plus("/{${NavConstants.TYPE_KEY}}/{${NavConstants.ID_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.ID_KEY) { type = NavType.IntType },
|
||||
navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) }
|
||||
)
|
||||
) { navBackStackEntry ->
|
||||
val args = navBackStackEntry.arguments
|
||||
val mediaType = args?.getSerializable(NavConstants.TYPE_KEY) as MediaViewType
|
||||
|
||||
when (mediaType) {
|
||||
MediaViewType.PERSON -> {
|
||||
PersonDetailView(
|
||||
appNavController = appNavController,
|
||||
personId = args.getInt(NavConstants.ID_KEY)
|
||||
)
|
||||
}
|
||||
MediaViewType.LIST -> {
|
||||
ListDetailView(
|
||||
appNavController = appNavController,
|
||||
itemId = args.getInt(NavConstants.ID_KEY),
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
MediaDetailView(
|
||||
appNavController = appNavController,
|
||||
itemId = args.getInt(NavConstants.ID_KEY),
|
||||
type = mediaType,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
composable(
|
||||
MainNavItem.SettingsView.route.plus("/{${NavConstants.SETTINGS_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.SETTINGS_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
val route = it.arguments?.getString(NavConstants.SETTINGS_KEY)
|
||||
SettingsTab(
|
||||
appNavController = appNavController,
|
||||
activity = this@MainActivity,
|
||||
route = route
|
||||
)
|
||||
}
|
||||
composable(MainNavItem.SettingsView.route) {
|
||||
SettingsTab(appNavController = appNavController, activity = this@MainActivity)
|
||||
}
|
||||
composable(
|
||||
route = MainNavItem.SearchView.route.plus("/{${NavConstants.SEARCH_ID_KEY}}/{${NavConstants.SEARCH_TITLE_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.SEARCH_ID_KEY) { type = NavType.IntType },
|
||||
navArgument(NavConstants.SEARCH_TITLE_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
it.arguments?.let { arguments ->
|
||||
val (type, title) = if (preferences.multiSearch) {
|
||||
Pair(
|
||||
MediaViewType.MIXED,
|
||||
stringResource(id = R.string.search_all_title)
|
||||
)
|
||||
} else {
|
||||
Pair(
|
||||
MediaViewType[arguments.getInt(NavConstants.SEARCH_ID_KEY)],
|
||||
arguments.getString(NavConstants.SEARCH_TITLE_KEY) ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
SearchScreen(
|
||||
appNavController = appNavController,
|
||||
title = title,
|
||||
mediaViewType = type
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = MainNavItem.WebLinkView.route.plus("/{${NavConstants.WEB_LINK_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.WEB_LINK_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
val url = it.arguments?.getString(NavConstants.WEB_LINK_KEY)
|
||||
url?.let {
|
||||
WebLinkView(url = url, appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = MainNavItem.AccountView.route,
|
||||
deepLinks = listOf(
|
||||
navDeepLink { uriPattern = "app://tvtime.auth.{${NavConstants.ACCOUNT_KEY}}" }
|
||||
)
|
||||
) {
|
||||
val deepLink = it.arguments?.getString(NavConstants.ACCOUNT_KEY)
|
||||
AccountView(
|
||||
appNavController = appNavController,
|
||||
doSignInPartTwo = deepLink == NavConstants.AUTH_REDIRECT_PAGE
|
||||
)
|
||||
}
|
||||
composable(
|
||||
route = MainNavItem.AboutView.route
|
||||
) {
|
||||
AboutView(appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppKeyboardFocusManager() {
|
||||
val context = LocalContext.current
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.deserializer
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.BaseDeserializer
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.KnownFor
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.KnownForMovie
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.KnownForTv
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class KnownForDeserializer: BaseDeserializer<KnownFor>() {
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.deserializer
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.BaseDeserializer
|
||||
@@ -8,7 +7,7 @@ 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.SortableSearchResult
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class SortableSearchResultDeserializer: BaseDeserializer<SortableSearchResult>() {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class DetailCast(
|
||||
@SerializedName("id") val id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class DetailCrew(
|
||||
@SerializedName("id") val id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
abstract class KnownFor(
|
||||
@SerializedName("backdrop_path") val backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class KnownForMovie(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class KnownForTv(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class MarkAsFavoriteBody(
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
|
||||
@@ -4,7 +4,7 @@ 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.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
abstract class SearchResultMedia(
|
||||
@SerializedName("overview") val overview: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class SearchResultMovie(
|
||||
id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class SearchResultPerson(
|
||||
@SerializedName("profile_path") val profilePath: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class SearchResultTv(
|
||||
id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
abstract class SortableSearchResult(
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class WatchlistBody(
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.BaseDeserializer
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListItem
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListMovie
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListTv
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class ListItemDeserializer: BaseDeserializer<ListItem>() {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class AddToListBody(
|
||||
@SerializedName("items") val items: List<AddToListBodyItem>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class DeleteListItemsBody(
|
||||
@SerializedName("items") val items: List<DeleteListItemsItem>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
abstract class ListItem(
|
||||
@SerializedName("backdrop_path") val backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class ListItemStatusResponse(
|
||||
statusMessage: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class ListMovie(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class ListTv(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
class UpdateListItemBody(
|
||||
@SerializedName("items") val items: List<UpdateListItemBodyItem>
|
||||
|
||||
@@ -8,7 +8,7 @@ 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.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koin.core.component.KoinComponent
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.components
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -25,13 +25,9 @@ import com.google.accompanist.pager.PagerState
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
|
||||
import com.owenlejeune.tvtime.ui.components.PosterItem
|
||||
import com.owenlejeune.tvtime.ui.components.RatingRing
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -12,7 +12,6 @@ import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -22,7 +21,8 @@ import androidx.constraintlayout.compose.Dimension
|
||||
import androidx.navigation.NavController
|
||||
import coil.compose.AsyncImage
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -45,7 +45,7 @@ fun MediaResultCard(
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
"${AppNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -39,14 +39,13 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -130,7 +129,7 @@ fun ProfileMenuOverlay(
|
||||
ProfileMenuItem(
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
appNavController.navigate(MainNavItem.AccountView.route)
|
||||
appNavController.navigate(AppNavItem.AccountView.route)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
@@ -147,7 +146,7 @@ fun ProfileMenuOverlay(
|
||||
ProfileMenuItem(
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
appNavController.navigate(MainNavItem.SettingsView.route)
|
||||
appNavController.navigate(AppNavItem.SettingsView.route)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
@@ -163,7 +162,7 @@ fun ProfileMenuOverlay(
|
||||
ProfileMenuItem(
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
appNavController.navigate(MainNavItem.AboutView.route)
|
||||
appNavController.navigate(AppNavItem.AboutView.route)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
@@ -187,7 +186,7 @@ fun ProfileMenuOverlay(
|
||||
} else {
|
||||
SessionManager.signInPart1(context) {
|
||||
appNavController.navigate(
|
||||
MainNavItem.WebLinkView.route.plus("/$it")
|
||||
AppNavItem.WebLinkView.route.plus("/$it")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main.tabs.top
|
||||
package com.owenlejeune.tvtime.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -17,14 +17,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.PagerState
|
||||
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.TabNavItem
|
||||
import com.owenlejeune.tvtime.utils.types.TabNavItem
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@@ -17,7 +17,6 @@ import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.ArrowDropUp
|
||||
import androidx.compose.material.icons.filled.Error
|
||||
@@ -69,8 +68,8 @@ import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AuthorDetails
|
||||
import com.owenlejeune.tvtime.extensions.unlessEmpty
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -211,7 +210,7 @@ fun SearchView(
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
|
||||
) {
|
||||
val route = "${MainNavItem.SearchView.route}/${mediaType.ordinal}/$title"
|
||||
val route = "${AppNavItem.SearchView.route}/${mediaType.ordinal}/$title"
|
||||
if (preferences.showSearchBar) {
|
||||
SearchBar(
|
||||
placeholder = title
|
||||
|
||||
@@ -11,11 +11,12 @@ 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.ui.screens.main.AccountTabContent
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.RecommendedAccountTabContent
|
||||
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.TabNavItem
|
||||
import org.koin.core.component.inject
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navArgument
|
||||
import androidx.navigation.navDeepLink
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.screens.SearchScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.AboutScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.AccountScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.ListDetailScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaDetailScreen
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.PersonDetailScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.SettingsScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.WebLinkScreen
|
||||
import com.owenlejeune.tvtime.ui.screens.HomeScreen
|
||||
import com.owenlejeune.tvtime.utils.NavConstants
|
||||
import org.koin.java.KoinJavaComponent
|
||||
|
||||
@Composable
|
||||
fun AppNavigationHost(
|
||||
startDestination: String = AppNavItem.MainView.route,
|
||||
mainNavStartRoute: String = AppNavItem.Items[0].route,
|
||||
appNavController: NavHostController,
|
||||
windowSize: WindowSizeClass,
|
||||
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
|
||||
) {
|
||||
NavHost(navController = appNavController, startDestination = startDestination) {
|
||||
composable(AppNavItem.MainView.route) {
|
||||
HomeScreen(
|
||||
appNavController = appNavController,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
composable(
|
||||
AppNavItem.DetailView.route.plus("/{${NavConstants.TYPE_KEY}}/{${NavConstants.ID_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.ID_KEY) { type = NavType.IntType },
|
||||
navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) }
|
||||
)
|
||||
) { navBackStackEntry ->
|
||||
val args = navBackStackEntry.arguments
|
||||
val mediaType = args?.getSerializable(NavConstants.TYPE_KEY) as MediaViewType
|
||||
|
||||
when (mediaType) {
|
||||
MediaViewType.PERSON -> {
|
||||
PersonDetailScreen(
|
||||
appNavController = appNavController,
|
||||
personId = args.getInt(NavConstants.ID_KEY)
|
||||
)
|
||||
}
|
||||
MediaViewType.LIST -> {
|
||||
ListDetailScreen(
|
||||
appNavController = appNavController,
|
||||
itemId = args.getInt(NavConstants.ID_KEY),
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
MediaDetailScreen(
|
||||
appNavController = appNavController,
|
||||
itemId = args.getInt(NavConstants.ID_KEY),
|
||||
type = mediaType,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
composable(
|
||||
AppNavItem.SettingsView.route.plus("/{${NavConstants.SETTINGS_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.SETTINGS_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
val route = it.arguments?.getString(NavConstants.SETTINGS_KEY)
|
||||
SettingsScreen(
|
||||
appNavController = appNavController,
|
||||
route = route
|
||||
)
|
||||
}
|
||||
composable(AppNavItem.SettingsView.route) {
|
||||
SettingsScreen(appNavController = appNavController)
|
||||
}
|
||||
composable(
|
||||
route = AppNavItem.SearchView.route.plus("/{${NavConstants.SEARCH_ID_KEY}}/{${NavConstants.SEARCH_TITLE_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.SEARCH_ID_KEY) { type = NavType.IntType },
|
||||
navArgument(NavConstants.SEARCH_TITLE_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
it.arguments?.let { arguments ->
|
||||
val (type, title) = if (preferences.multiSearch) {
|
||||
Pair(
|
||||
MediaViewType.MIXED,
|
||||
stringResource(id = R.string.search_all_title)
|
||||
)
|
||||
} else {
|
||||
Pair(
|
||||
MediaViewType[arguments.getInt(NavConstants.SEARCH_ID_KEY)],
|
||||
arguments.getString(NavConstants.SEARCH_TITLE_KEY) ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
SearchScreen(
|
||||
appNavController = appNavController,
|
||||
title = title,
|
||||
mediaViewType = type
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = AppNavItem.WebLinkView.route.plus("/{${NavConstants.WEB_LINK_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.WEB_LINK_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
val url = it.arguments?.getString(NavConstants.WEB_LINK_KEY)
|
||||
url?.let {
|
||||
WebLinkScreen(url = url, appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = AppNavItem.AccountView.route,
|
||||
deepLinks = listOf(
|
||||
navDeepLink { uriPattern = "app://tvtime.auth.{${NavConstants.ACCOUNT_KEY}}" }
|
||||
)
|
||||
) {
|
||||
val deepLink = it.arguments?.getString(NavConstants.ACCOUNT_KEY)
|
||||
AccountScreen(
|
||||
appNavController = appNavController,
|
||||
doSignInPartTwo = deepLink == NavConstants.AUTH_REDIRECT_PAGE
|
||||
)
|
||||
}
|
||||
composable(route = AppNavItem.AboutView.route) {
|
||||
AboutScreen(appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AppNavItem(val route: String) {
|
||||
|
||||
companion object {
|
||||
val Items = listOf(MainView, DetailView, SettingsView)
|
||||
}
|
||||
|
||||
object MainView: AppNavItem("main_route")
|
||||
object DetailView: AppNavItem("detail_route")
|
||||
object SettingsView: AppNavItem("settings_route")
|
||||
object SearchView: AppNavItem("search_route")
|
||||
object WebLinkView: AppNavItem("web_link_route")
|
||||
object AccountView: AppNavItem("account_route")
|
||||
object AboutView: AppNavItem("about_route")
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
sealed class BottomNavItem(
|
||||
stringRes: Int,
|
||||
val icon: Int,
|
||||
val route: String,
|
||||
private val orderGetter: (AppPreferences) -> Int,
|
||||
private val orderSetter: (AppPreferences, Int) -> Unit
|
||||
): KoinComponent {
|
||||
|
||||
private val appPreferences: AppPreferences by inject()
|
||||
private val resourceUtils: ResourceUtils by inject()
|
||||
|
||||
val name = resourceUtils.getString(stringRes)
|
||||
var order: Int
|
||||
get() = orderGetter.invoke(appPreferences)
|
||||
set(value) { orderSetter.invoke(appPreferences, value) }
|
||||
|
||||
companion object {
|
||||
|
||||
val SortedItems
|
||||
get() = Items.filter { it.order > -1 }.sortedBy { it.order }.ifEmpty { Items }
|
||||
|
||||
val Items by lazy {
|
||||
listOf(Movies, TV, People, Account)
|
||||
}
|
||||
|
||||
fun getByRoute(route: String?): BottomNavItem? {
|
||||
return when (route) {
|
||||
Movies.route -> Movies
|
||||
TV.route -> TV
|
||||
Account.route -> Account
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Movies: BottomNavItem(
|
||||
R.string.nav_movies_title,
|
||||
R.drawable.ic_movie,
|
||||
"movies_route",
|
||||
{ it.moviesTabPosition },
|
||||
{ p, i -> p.moviesTabPosition = i }
|
||||
)
|
||||
object TV: BottomNavItem(
|
||||
R.string.nav_tv_title,
|
||||
R.drawable.ic_tv,
|
||||
"tv_route",
|
||||
{ it.tvTabPosition },
|
||||
{ p, i -> p.tvTabPosition = i }
|
||||
)
|
||||
object Account: BottomNavItem(
|
||||
R.string.nav_account_title,
|
||||
R.drawable.ic_person,
|
||||
"account_route",
|
||||
{
|
||||
// if (SessionManager.currentSession.value?.isAuthorized == true) {
|
||||
// it.accountTabPosition
|
||||
// } else {
|
||||
-2
|
||||
// }
|
||||
},
|
||||
{ p, i -> p.accountTabPosition = i }
|
||||
)
|
||||
object People: BottomNavItem(
|
||||
R.string.nav_people_title,
|
||||
R.drawable.ic_face,
|
||||
"people_route",
|
||||
{ it.peopleTabPosition },
|
||||
{ p, i -> p.peopleTabPosition = i }
|
||||
)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.screens.AccountViewContent
|
||||
import com.owenlejeune.tvtime.ui.screens.new.tabs.MediaTab
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.PeopleTab
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@Composable
|
||||
fun HomeScreenNavHost(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
startDestination: String = HomeScreenNavItem.SortedItems[0].route
|
||||
) {
|
||||
NavHost(navController = navController, startDestination = startDestination) {
|
||||
composable(HomeScreenNavItem.Movies.route) {
|
||||
appBarActions.value = {}
|
||||
MediaTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
mediaType = MediaViewType.MOVIE,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
composable(HomeScreenNavItem.TV.route) {
|
||||
appBarActions.value = {}
|
||||
MediaTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
mediaType = MediaViewType.TV,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
composable(route = HomeScreenNavItem.Account.route) {
|
||||
AccountViewContent(appNavController = appNavController)
|
||||
fab.value = {}
|
||||
}
|
||||
composable(HomeScreenNavItem.People.route) {
|
||||
appBarActions.value = {}
|
||||
PeopleTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class HomeScreenNavItem(
|
||||
stringRes: Int,
|
||||
val icon: Int,
|
||||
val route: String,
|
||||
private val orderGetter: (AppPreferences) -> Int,
|
||||
private val orderSetter: (AppPreferences, Int) -> Unit
|
||||
): KoinComponent {
|
||||
|
||||
private val appPreferences: AppPreferences by inject()
|
||||
private val resourceUtils: ResourceUtils by inject()
|
||||
|
||||
val name = resourceUtils.getString(stringRes)
|
||||
var order: Int
|
||||
get() = orderGetter.invoke(appPreferences)
|
||||
set(value) { orderSetter.invoke(appPreferences, value) }
|
||||
|
||||
companion object {
|
||||
|
||||
val SortedItems
|
||||
get() = Items.filter { it.order > -1 }.sortedBy { it.order }.ifEmpty { Items }
|
||||
|
||||
val Items by lazy {
|
||||
listOf(Movies, TV, People, Account)
|
||||
}
|
||||
|
||||
fun getByRoute(route: String?): HomeScreenNavItem? {
|
||||
return when (route) {
|
||||
Movies.route -> Movies
|
||||
TV.route -> TV
|
||||
Account.route -> Account
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Movies: HomeScreenNavItem(
|
||||
R.string.nav_movies_title,
|
||||
R.drawable.ic_movie,
|
||||
"movies_route",
|
||||
{ it.moviesTabPosition },
|
||||
{ p, i -> p.moviesTabPosition = i }
|
||||
)
|
||||
object TV: HomeScreenNavItem(
|
||||
R.string.nav_tv_title,
|
||||
R.drawable.ic_tv,
|
||||
"tv_route",
|
||||
{ it.tvTabPosition },
|
||||
{ p, i -> p.tvTabPosition = i }
|
||||
)
|
||||
object Account: HomeScreenNavItem(
|
||||
R.string.nav_account_title,
|
||||
R.drawable.ic_person,
|
||||
"account_route",
|
||||
{
|
||||
// if (SessionManager.currentSession.value?.isAuthorized == true) {
|
||||
// it.accountTabPosition
|
||||
// } else {
|
||||
-2
|
||||
// }
|
||||
},
|
||||
{ p, i -> p.accountTabPosition = i }
|
||||
)
|
||||
object People: HomeScreenNavItem(
|
||||
R.string.nav_people_title,
|
||||
R.drawable.ic_face,
|
||||
"people_route",
|
||||
{ it.peopleTabPosition },
|
||||
{ p, i -> p.peopleTabPosition = i }
|
||||
)
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
|
||||
sealed class MainNavItem(val route: String) {
|
||||
|
||||
companion object {
|
||||
val Items = listOf(MainView, DetailView, SettingsView)
|
||||
}
|
||||
|
||||
object MainView: MainNavItem("main_route")
|
||||
object DetailView: MainNavItem("detail_route")
|
||||
object SettingsView: MainNavItem("settings_route")
|
||||
object SearchView: MainNavItem("search_route")
|
||||
object WebLinkView: MainNavItem("web_link_route")
|
||||
object AccountView: MainNavItem("account_route")
|
||||
object AboutView: MainNavItem("about_route")
|
||||
|
||||
}
|
||||
@@ -5,10 +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.ui.screens.main.MediaTabContent
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.api.tmdb.viewmodel.MediaTabViewModel
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.MediaTabContent
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
import com.owenlejeune.tvtime.utils.types.TabNavItem
|
||||
import org.koin.core.component.inject
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navDeepLink
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.*
|
||||
import com.owenlejeune.tvtime.utils.NavConstants
|
||||
|
||||
@Composable
|
||||
fun MainNavGraph(
|
||||
activity: AppCompatActivity,
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
startDestination: String = BottomNavItem.SortedItems[0].route
|
||||
) {
|
||||
NavHost(navController = navController, startDestination = startDestination) {
|
||||
composable(BottomNavItem.Movies.route) {
|
||||
appBarActions.value = {}
|
||||
MediaTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
mediaType = MediaViewType.MOVIE,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
composable(BottomNavItem.TV.route) {
|
||||
appBarActions.value = {}
|
||||
MediaTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
mediaType = MediaViewType.TV,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
composable(route = BottomNavItem.Account.route) {
|
||||
AccountViewContent(appNavController = appNavController)
|
||||
fab.value = {}
|
||||
}
|
||||
composable(BottomNavItem.People.route) {
|
||||
appBarActions.value = {}
|
||||
PeopleTab(
|
||||
appBarTitle = appBarTitle,
|
||||
appNavController = appNavController,
|
||||
fab = fab
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
@@ -58,7 +58,7 @@ import dev.jeziellago.compose.markdowntext.MarkdownText
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AboutView(
|
||||
fun AboutScreen(
|
||||
appNavController: NavController
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -36,8 +36,10 @@ import com.owenlejeune.tvtime.ui.components.AccountIcon
|
||||
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
||||
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.main.tabs.top.ScrollableTabs
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.components.ScrollableTabs
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -45,7 +47,7 @@ import kotlin.reflect.KClass
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AccountView(
|
||||
fun AccountScreen(
|
||||
appNavController: NavHostController,
|
||||
doSignInPartTwo: Boolean = false
|
||||
) {
|
||||
@@ -303,7 +305,7 @@ fun RecommendedAccountTabContent(
|
||||
lazyPagingItems = mediaListItems,
|
||||
onClick = { id ->
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
"${AppNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,313 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationRail
|
||||
import androidx.compose.material3.NavigationRailItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.material3.rememberTopAppBarScrollState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
||||
import com.owenlejeune.tvtime.extensions.navigateInBottomBar
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.AccountIcon
|
||||
import com.owenlejeune.tvtime.ui.components.ProfileMenuContainer
|
||||
import com.owenlejeune.tvtime.ui.components.ProfileMenuDefaults
|
||||
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavHost
|
||||
import org.koin.java.KoinJavaComponent
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
appNavController: NavHostController,
|
||||
mainNavStartRoute: String = HomeScreenNavItem.SortedItems[0].route,
|
||||
windowSize: WindowSizeClass
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||
val scrollBehavior = remember(decayAnimationSpec) {
|
||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||
}
|
||||
|
||||
val appBarTitle = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||
val appBarActions = remember { mutableStateOf<@Composable RowScope.() -> Unit>({}) }
|
||||
val fab = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||
|
||||
val showProfileMenuOverlay = remember { mutableStateOf(false) }
|
||||
val navigationIcon = @Composable {
|
||||
AccountIcon(
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
size = 32.dp,
|
||||
onClick = { showProfileMenuOverlay.value = true }
|
||||
)
|
||||
}
|
||||
|
||||
val defaultNavBarColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.08f).compositeOver(background = MaterialTheme.colorScheme.surface)
|
||||
|
||||
ProfileMenuContainer(
|
||||
appNavController = appNavController,
|
||||
visible = showProfileMenuOverlay.value,
|
||||
onDismissRequest = { showProfileMenuOverlay.value = false },
|
||||
colors = ProfileMenuDefaults.systemBarColors(navBarColor = defaultNavBarColor)
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
TopBar(
|
||||
title = appBarTitle.value,
|
||||
scrollBehavior = scrollBehavior,
|
||||
appBarActions = appBarActions,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
fab.value()
|
||||
},
|
||||
bottomBar = {
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
BottomNavBar(navController = navController)
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
MainContent(
|
||||
windowSize = windowSize,
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
topBarScrollBehaviour = scrollBehavior,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
title: @Composable () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {}
|
||||
) {
|
||||
LargeTopAppBar(
|
||||
title = title,
|
||||
scrollBehavior = scrollBehavior,
|
||||
colors = TopAppBarDefaults
|
||||
.largeTopAppBarColors(
|
||||
scrolledContainerColor = MaterialTheme.colorScheme.background
|
||||
),
|
||||
actions = {
|
||||
appBarActions.value(this)
|
||||
},
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomNavBar(
|
||||
navController: NavController,
|
||||
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
|
||||
NavigationBar {
|
||||
HomeScreenNavItem.SortedItems.forEach { item ->
|
||||
val isSelected = currentRoute == item.route
|
||||
NavigationBarItem(
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.clip(RoundedCornerShape(24.dp)),
|
||||
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
||||
label = {
|
||||
val name = if (preferences.showBottomTabLabels) item.name else " "
|
||||
Text(text = name)
|
||||
},
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
if (!isSelected) {
|
||||
navController.navigateInBottomBar(item.route)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainContent(
|
||||
windowSize: WindowSizeClass,
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
mainNavStartRoute: String = HomeScreenNavItem.SortedItems[0].route
|
||||
) {
|
||||
if (windowSize == WindowSizeClass.Expanded) {
|
||||
DualColumnMainContent(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
topBarScrollBehaviour = topBarScrollBehaviour,
|
||||
mainNavStartRoute = mainNavStartRoute,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
} else {
|
||||
SingleColumnMainContent(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleColumnMainContent(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
mainNavStartRoute: String = HomeScreenNavItem.SortedItems[0].route
|
||||
) {
|
||||
MainMediaView(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DualColumnMainContent(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
mainNavStartRoute: String = HomeScreenNavItem.SortedItems[0].route,
|
||||
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
|
||||
Row(modifier = Modifier.fillMaxSize()) {
|
||||
NavigationRail {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
HomeScreenNavItem.SortedItems.forEachIndexed { index, item ->
|
||||
val isSelected = currentRoute == item.route
|
||||
NavigationRailItem(
|
||||
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
||||
label = { if (preferences.showBottomTabLabels) Text(item.name) },
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
if (!isSelected) {
|
||||
navController.navigateInBottomBar(item.route)
|
||||
}
|
||||
}
|
||||
)
|
||||
if (index < HomeScreenNavItem.SortedItems.size - 1) {
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
Column {
|
||||
TopBar(
|
||||
title = appBarTitle.value,
|
||||
scrollBehavior = topBarScrollBehaviour,
|
||||
appBarActions = appBarActions,
|
||||
navigationIcon = navigationIcon
|
||||
)
|
||||
MainMediaView(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
mainNavStartRoute = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainMediaView(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
fab: MutableState<@Composable () -> Unit>,
|
||||
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||
appBarActions: MutableState<RowScope.() -> Unit> = mutableStateOf({}),
|
||||
mainNavStartRoute: String = HomeScreenNavItem.SortedItems[0].route
|
||||
) {
|
||||
val activity = LocalContext.current as Activity
|
||||
Column {
|
||||
BackHandler(enabled = true) {
|
||||
activity.finish()
|
||||
}
|
||||
|
||||
HomeScreenNavHost(
|
||||
appNavController = appNavController,
|
||||
navController = navController,
|
||||
fab = fab,
|
||||
appBarTitle = appBarTitle,
|
||||
appBarActions = appBarActions,
|
||||
startDestination = mainNavStartRoute
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
@@ -45,7 +45,9 @@ import com.owenlejeune.tvtime.extensions.unlessEmpty
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.Spinner
|
||||
import com.owenlejeune.tvtime.ui.components.SwitchPreference
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.components.RatingView
|
||||
import com.owenlejeune.tvtime.ui.theme.*
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
@@ -60,7 +62,7 @@ import kotlin.math.roundToInt
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ListDetailView(
|
||||
fun ListDetailScreen(
|
||||
appNavController: NavController,
|
||||
itemId: Int?,
|
||||
windowSize: WindowSizeClass,
|
||||
@@ -457,7 +459,7 @@ private fun ListItemView(
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${listItem.mediaType}/${listItem.id}"
|
||||
"${AppNavItem.DetailView.route}/${listItem.mediaType}/${listItem.id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -575,7 +577,7 @@ private fun ActionButtonRow(listItem: ListItem) {
|
||||
contentDescription = stringResource(id = R.string.favourite_label),
|
||||
isSelected = isFavourited,
|
||||
filledIconColor = FavoriteSelected,
|
||||
onClick = ::addToFavorite
|
||||
onClick = ::listAddToFavorite
|
||||
)
|
||||
|
||||
ActionButton(
|
||||
@@ -585,7 +587,7 @@ private fun ActionButtonRow(listItem: ListItem) {
|
||||
contentDescription = "",
|
||||
isSelected = isWatchlisted,
|
||||
filledIconColor = WatchlistSelected,
|
||||
onClick = ::addToWatchlist
|
||||
onClick = ::listAddToWatchlist
|
||||
)
|
||||
|
||||
val context = LocalContext.current
|
||||
@@ -604,7 +606,7 @@ private fun ActionButtonRow(listItem: ListItem) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addToWatchlist(
|
||||
private fun listAddToWatchlist(
|
||||
context: Context,
|
||||
itemId: Int,
|
||||
type: MediaViewType,
|
||||
@@ -629,7 +631,7 @@ private fun addToWatchlist(
|
||||
}
|
||||
}
|
||||
|
||||
private fun addToFavorite(
|
||||
private fun listAddToFavorite(
|
||||
context: Context,
|
||||
itemId: Int,
|
||||
type: MediaViewType,
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -16,7 +14,6 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Movie
|
||||
import androidx.compose.material.icons.filled.Send
|
||||
import androidx.compose.material.icons.outlined.ExpandLess
|
||||
import androidx.compose.material.icons.outlined.ExpandMore
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
@@ -31,7 +28,6 @@ import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
@@ -55,9 +51,11 @@ import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
||||
import com.owenlejeune.tvtime.extensions.listItems
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.TabNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.utils.types.TabNavItem
|
||||
import com.owenlejeune.tvtime.ui.components.DetailHeader
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.components.Tabs
|
||||
import com.owenlejeune.tvtime.ui.theme.FavoriteSelected
|
||||
import com.owenlejeune.tvtime.ui.theme.RatingSelected
|
||||
import com.owenlejeune.tvtime.ui.theme.WatchlistSelected
|
||||
@@ -71,7 +69,7 @@ import java.text.DecimalFormat
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun MediaDetailView(
|
||||
fun MediaDetailScreen(
|
||||
appNavController: NavController,
|
||||
itemId: Int?,
|
||||
type: MediaViewType,
|
||||
@@ -780,7 +778,7 @@ fun FavoriteButton(
|
||||
contentDescription = "",
|
||||
isSelected = isFavourited,
|
||||
filledIconColor = FavoriteSelected,
|
||||
onClick = ::addToFavorite
|
||||
onClick = ::mediaAddToFavorite
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1140,7 +1138,7 @@ private fun CastCrewCard(appNavController: NavController, person: Person) {
|
||||
subtitleTextColor = MaterialTheme.colorScheme.onSecondary,
|
||||
onItemClicked = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${MediaViewType.PERSON}/${person.id}"
|
||||
"${AppNavItem.DetailView.route}/${MediaViewType.PERSON}/${person.id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -1186,7 +1184,7 @@ fun SimilarContentCard(
|
||||
imageUrl = TmdbUtils.getFullPosterPath(content),
|
||||
onItemClicked = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaType}/${content.id}"
|
||||
"${AppNavItem.DetailView.route}/${mediaType}/${content.id}"
|
||||
)
|
||||
},
|
||||
placeholder = Icons.Filled.Movie
|
||||
@@ -1573,7 +1571,7 @@ private fun addToWatchlist(
|
||||
}
|
||||
}
|
||||
|
||||
private fun addToFavorite(
|
||||
private fun mediaAddToFavorite(
|
||||
context: Context,
|
||||
itemId: Int,
|
||||
type: MediaViewType,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.background
|
||||
@@ -28,7 +28,9 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.PersonCreditsResponse
|
||||
import com.owenlejeune.tvtime.ui.components.ContentCard
|
||||
import com.owenlejeune.tvtime.ui.components.ExpandableContentCard
|
||||
import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.ui.components.DetailHeader
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -37,7 +39,7 @@ import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun PersonDetailView(
|
||||
fun PersonDetailScreen(
|
||||
appNavController: NavController,
|
||||
personId: Int?
|
||||
) {
|
||||
@@ -125,7 +127,7 @@ fun PersonDetailView(
|
||||
onItemClicked = {
|
||||
personId?.let {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${content.mediaType}/${content.id}"
|
||||
"${AppNavItem.DetailView.route}/${content.mediaType}/${content.id}"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -171,7 +173,7 @@ fun PersonDetailView(
|
||||
onItemClicked = {
|
||||
personId?.let {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${content.mediaType}/${content.id}"
|
||||
"${AppNavItem.DetailView.route}/${content.mediaType}/${content.id}"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
@@ -14,17 +11,13 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavHostController
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.DetailService
|
||||
@@ -33,9 +26,8 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
|
||||
import com.owenlejeune.tvtime.extensions.listItems
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaResultCard
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
@@ -37,7 +37,7 @@ import com.owenlejeune.tvtime.OnboardingActivity
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.ui.views.HomeTabRecyclerAdapter
|
||||
import com.owenlejeune.tvtime.ui.views.ItemMoveCallback
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
@@ -49,9 +49,8 @@ import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsTab(
|
||||
fun SettingsScreen(
|
||||
appNavController: NavController,
|
||||
activity: AppCompatActivity,
|
||||
route: String? = null,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
@@ -110,6 +109,7 @@ fun SettingsTab(
|
||||
.padding(all = 24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(18.dp)
|
||||
) {
|
||||
val activity = LocalContext.current as AppCompatActivity
|
||||
SettingsPage.getByRoute(route).apply {
|
||||
appBarTitle.value = name
|
||||
restoreAction.value = resetPreferencesHandler
|
||||
@@ -188,7 +188,7 @@ private fun TopLevelSettingsCard(
|
||||
.wrapContentHeight()
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate("${MainNavItem.SettingsView.route}/${settingsView.route}")
|
||||
appNavController.navigate("${AppNavItem.SettingsView.route}/${settingsView.route}")
|
||||
}
|
||||
)
|
||||
) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -30,7 +30,7 @@ import org.koin.core.component.inject
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WebLinkView(
|
||||
fun WebLinkScreen(
|
||||
url: String,
|
||||
appNavController: NavController
|
||||
) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Text
|
||||
@@ -15,10 +15,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.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||
import com.owenlejeune.tvtime.ui.components.Tabs
|
||||
import com.owenlejeune.tvtime.api.tmdb.viewmodel.MediaTabViewModel
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
@@ -72,7 +73,7 @@ fun MediaTabContent(appNavController: NavHostController, mediaType: MediaViewTyp
|
||||
lazyPagingItems = mediaListItems,
|
||||
onClick = { id ->
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaType}/${id}"
|
||||
"${AppNavItem.DetailView.route}/${mediaType}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -1,20 +1,18 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.ui.components.PagingPeoplePosterGrid
|
||||
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||
import com.owenlejeune.tvtime.api.tmdb.viewmodel.PeopleTabViewModel
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
|
||||
@Composable
|
||||
fun PeopleTab(
|
||||
@@ -45,7 +43,7 @@ fun PeopleTab(
|
||||
},
|
||||
onClick = { id ->
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${MediaViewType.PERSON}/${id}"
|
||||
"${AppNavItem.DetailView.route}/${MediaViewType.PERSON}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -17,7 +17,7 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavItem
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
|
||||
@@ -27,14 +27,14 @@ class HomeTabRecyclerAdapter: RecyclerView.Adapter<HomeTabRecyclerAdapter.TabVie
|
||||
|
||||
class TabViewHolder(itemView: ComposeView): RecyclerView.ViewHolder(itemView)
|
||||
|
||||
private val pages: MutableList<BottomNavItem?>
|
||||
private val pages: MutableList<HomeScreenNavItem?>
|
||||
private val indexOfDivider
|
||||
get() = pages.indexOf(null)
|
||||
|
||||
init {
|
||||
val visiblePages = BottomNavItem.Items.filter { it.order > -1 }.sortedBy { it.order }
|
||||
val hiddenPages = BottomNavItem.Items.filter { it.order == -1 }
|
||||
pages = ArrayList<BottomNavItem?>().apply {
|
||||
val visiblePages = HomeScreenNavItem.Items.filter { it.order > -1 }.sortedBy { it.order }
|
||||
val hiddenPages = HomeScreenNavItem.Items.filter { it.order == -1 }
|
||||
pages = ArrayList<HomeScreenNavItem?>().apply {
|
||||
addAll(visiblePages)
|
||||
add(null)
|
||||
addAll(hiddenPages)
|
||||
@@ -67,7 +67,7 @@ class HomeTabRecyclerAdapter: RecyclerView.Adapter<HomeTabRecyclerAdapter.TabVie
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ItemRow(page: BottomNavItem) {
|
||||
private fun ItemRow(page: HomeScreenNavItem) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(50.dp),
|
||||
|
||||
@@ -16,7 +16,7 @@ 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.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
package com.owenlejeune.tvtime.utils.types
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.navigation
|
||||
package com.owenlejeune.tvtime.utils.types
|
||||
|
||||
import org.koin.core.component.KoinComponent
|
||||
|
||||
Reference in New Issue
Block a user