add development options to store and navigate to a saved route

This commit is contained in:
Owen LeJeune
2023-07-13 23:28:47 -04:00
parent 8d74d6ee53
commit 69f6911b72
19 changed files with 316 additions and 218 deletions

View File

@@ -35,6 +35,7 @@ class AppPreferences(context: Context) {
private val SHOW_BTAB_LABELS = "show_btab_labels" private val SHOW_BTAB_LABELS = "show_btab_labels"
private val SHOW_POSTER_TITLE = "show_poster_titles" private val SHOW_POSTER_TITLE = "show_poster_titles"
private val SHOW_NEXT_MCU = "show_next_mcu" private val SHOW_NEXT_MCU = "show_next_mcu"
private val STORED_TEST_ROUTE = "stored_test_route"
} }
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE) private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
@@ -135,6 +136,11 @@ class AppPreferences(context: Context) {
get() = preferences.getBoolean(SHOW_NEXT_MCU, showNextMcuProductionDefault) get() = preferences.getBoolean(SHOW_NEXT_MCU, showNextMcuProductionDefault)
set(value) { preferences.put(SHOW_NEXT_MCU, value) } set(value) { preferences.put(SHOW_NEXT_MCU, value) }
val storedTestRouteDefault: String = ""
var storedTestRoute: String
get() = preferences.getString(STORED_TEST_ROUTE, storedTestRouteDefault) ?: storedTestRouteDefault
set(value) { preferences.put(STORED_TEST_ROUTE, value) }
/********* Helpers ********/ /********* Helpers ********/
private fun SharedPreferences.put(key: String, value: Any?) { private fun SharedPreferences.put(key: String, value: Any?) {
edit().apply { edit().apply {

View File

@@ -0,0 +1,91 @@
package com.owenlejeune.tvtime.ui.components
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.Reply
import androidx.compose.material.icons.outlined.Upload
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun StoreRouteButton() {
val applicationViewModel = viewModel<ApplicationViewModel>()
val context = LocalContext.current
Box(
modifier = Modifier
.combinedClickable(
onClick = {
applicationViewModel.storedRoute.value = applicationViewModel.currentRoute.value
Toast.makeText(context, "Stored route \"${applicationViewModel.storedRoute.value}\"", Toast.LENGTH_SHORT).show()
},
onLongClick = {
applicationViewModel.storedRoute.value = ""
Toast.makeText(context, "Stored route \"\"", Toast.LENGTH_SHORT).show()
}
)
) {
Icon(
imageVector = Icons.Outlined.Upload,
contentDescription = null,
modifier = Modifier.align(Alignment.Center)
)
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun NavStoredRouteButton(appNavController: NavController) {
val applicationViewModel = viewModel<ApplicationViewModel>()
val context = LocalContext.current
Box(
modifier = Modifier
.clickable {
val route = applicationViewModel.storedRoute.value
if (route.isNotEmpty()) {
Toast.makeText(context, "Navigating to \"$route\"", Toast.LENGTH_SHORT).show()
appNavController.navigate(route)
}
}
) {
Icon(
imageVector = Icons.Outlined.Reply,
contentDescription = null,
modifier = Modifier.align(Alignment.Center)
)
}
}
@Composable
fun BackButton(navController: NavController) {
IconButton(
onClick = { navController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
}

View File

@@ -0,0 +1,72 @@
package com.owenlejeune.tvtime.ui.components
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.owenlejeune.tvtime.BuildConfig
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TVTTopAppBar(
title: @Composable () -> Unit,
appNavController: NavController,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = title,
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
navigationIcon = navigationIcon,
actions = {
if (BuildConfig.DEBUG) {
NavStoredRouteButton(appNavController = appNavController)
Spacer(modifier = Modifier.width(12.dp))
StoreRouteButton()
Spacer(modifier = Modifier.width(12.dp))
}
actions()
},
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TVTLargeTopAppBar(
title: @Composable () -> Unit,
appNavController: NavController,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
LargeTopAppBar(
title = title,
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors(scrolledContainerColor = MaterialTheme.colorScheme.background),
navigationIcon = navigationIcon,
actions = {
if (BuildConfig.DEBUG) {
NavStoredRouteButton(appNavController = appNavController)
Spacer(modifier = Modifier.width(12.dp))
StoreRouteButton()
Spacer(modifier = Modifier.width(12.dp))
}
actions()
}
)
}

View File

@@ -6,6 +6,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.NavType import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
@@ -30,6 +31,7 @@ import com.owenlejeune.tvtime.ui.screens.SearchScreen
import com.owenlejeune.tvtime.ui.screens.SeasonListScreen import com.owenlejeune.tvtime.ui.screens.SeasonListScreen
import com.owenlejeune.tvtime.ui.screens.SettingsScreen import com.owenlejeune.tvtime.ui.screens.SettingsScreen
import com.owenlejeune.tvtime.ui.screens.WebLinkScreen import com.owenlejeune.tvtime.ui.screens.WebLinkScreen
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.utils.NavConstants import com.owenlejeune.tvtime.utils.NavConstants
import com.owenlejeune.tvtime.utils.types.MediaViewType import com.owenlejeune.tvtime.utils.types.MediaViewType
import org.koin.java.KoinJavaComponent import org.koin.java.KoinJavaComponent
@@ -42,6 +44,8 @@ fun AppNavigationHost(
windowSize: WindowSizeClass, windowSize: WindowSizeClass,
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java) preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
) { ) {
val applicationViewModel = viewModel<ApplicationViewModel>()
NavHost( NavHost(
navController = appNavController, navController = appNavController,
startDestination = startDestination, startDestination = startDestination,
@@ -51,6 +55,7 @@ fun AppNavigationHost(
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, tween(500)) } popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, tween(500)) }
) { ) {
composable(route = AppNavItem.MainView.route) { composable(route = AppNavItem.MainView.route) {
applicationViewModel.currentRoute.value = AppNavItem.MainView.route
HomeScreen( HomeScreen(
appNavController = appNavController, appNavController = appNavController,
mainNavStartRoute = mainNavStartRoute, mainNavStartRoute = mainNavStartRoute,
@@ -64,27 +69,27 @@ fun AppNavigationHost(
navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) } navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) }
) )
) { navBackStackEntry -> ) { navBackStackEntry ->
val args = navBackStackEntry.arguments val mediaType = navBackStackEntry.arguments?.safeGetSerializable(NavConstants.TYPE_KEY, MediaViewType::class.java)!!
val mediaType = args?.getSerializable(NavConstants.TYPE_KEY) as MediaViewType val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.DetailView.withArgs(mediaType, id)
when (mediaType) { when (mediaType) {
MediaViewType.PERSON -> { MediaViewType.PERSON -> {
PersonDetailScreen( PersonDetailScreen(
appNavController = appNavController, appNavController = appNavController,
personId = args.getInt(NavConstants.ID_KEY) personId = id
) )
} }
MediaViewType.LIST -> { MediaViewType.LIST -> {
ListDetailScreen( ListDetailScreen(
appNavController = appNavController, appNavController = appNavController,
itemId = args.getInt(NavConstants.ID_KEY), itemId = id
windowSize = windowSize
) )
} }
else -> { else -> {
MediaDetailScreen( MediaDetailScreen(
appNavController = appNavController, appNavController = appNavController,
itemId = args.getInt(NavConstants.ID_KEY), itemId = id,
type = mediaType, type = mediaType,
windowSize = windowSize windowSize = windowSize
) )
@@ -92,6 +97,7 @@ fun AppNavigationHost(
} }
} }
composable(AppNavItem.SettingsView.route) { composable(AppNavItem.SettingsView.route) {
applicationViewModel.currentRoute.value = AppNavItem.SettingsView.route
SettingsScreen(appNavController = appNavController) SettingsScreen(appNavController = appNavController)
} }
composable( composable(
@@ -114,6 +120,7 @@ fun AppNavigationHost(
) )
} }
applicationViewModel.currentRoute.value = AppNavItem.SearchView.withArgs(type, title)
SearchScreen( SearchScreen(
appNavController = appNavController, appNavController = appNavController,
title = title, title = title,
@@ -129,6 +136,7 @@ fun AppNavigationHost(
) { ) {
val url = it.arguments?.getString(NavConstants.WEB_LINK_KEY) val url = it.arguments?.getString(NavConstants.WEB_LINK_KEY)
url?.let { url?.let {
applicationViewModel.currentRoute.value = AppNavItem.WebLinkView.withArgs(url)
WebLinkScreen(url = url, appNavController = appNavController) WebLinkScreen(url = url, appNavController = appNavController)
} }
} }
@@ -139,12 +147,14 @@ fun AppNavigationHost(
) )
) { ) {
val deepLink = it.arguments?.getString(NavConstants.ACCOUNT_KEY) val deepLink = it.arguments?.getString(NavConstants.ACCOUNT_KEY)
applicationViewModel.currentRoute.value = AppNavItem.AccountView.route
AccountScreen( AccountScreen(
appNavController = appNavController, appNavController = appNavController,
doSignInPartTwo = deepLink == NavConstants.AUTH_REDIRECT_PAGE doSignInPartTwo = deepLink == NavConstants.AUTH_REDIRECT_PAGE
) )
} }
composable(route = AppNavItem.AboutView.route) { composable(route = AppNavItem.AboutView.route) {
applicationViewModel.currentRoute.value = AppNavItem.AboutView.route
AboutScreen(appNavController = appNavController) AboutScreen(appNavController = appNavController)
} }
composable( composable(
@@ -159,6 +169,7 @@ fun AppNavigationHost(
val keywords = navBackStackEntry.arguments?.getString(NavConstants.KEYWORD_NAME_KEY) ?: "" val keywords = navBackStackEntry.arguments?.getString(NavConstants.KEYWORD_NAME_KEY) ?: ""
val id = navBackStackEntry.arguments?.getInt(NavConstants.KEYWORD_ID_KEY)!! val id = navBackStackEntry.arguments?.getInt(NavConstants.KEYWORD_ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.KeywordsView.withArgs(type, keywords, id)
KeywordResultsScreen( KeywordResultsScreen(
type = type, type = type,
keyword = keywords, keyword = keywords,
@@ -174,6 +185,7 @@ fun AppNavigationHost(
) { navBackStackEntry -> ) { navBackStackEntry ->
val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!! val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.KnownForView.withArgs(id)
KnownForScreen(appNavController = appNavController, id = id) KnownForScreen(appNavController = appNavController, id = id)
} }
composable( composable(
@@ -186,6 +198,7 @@ fun AppNavigationHost(
val type = navBackStackEntry.arguments?.safeGetSerializable(NavConstants.TYPE_KEY, MediaViewType::class.java)!! val type = navBackStackEntry.arguments?.safeGetSerializable(NavConstants.TYPE_KEY, MediaViewType::class.java)!!
val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!! val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.GalleryView.withArgs(type, id)
GalleryView(id = id, type = type, appNavController = appNavController) GalleryView(id = id, type = type, appNavController = appNavController)
} }
composable( composable(
@@ -196,10 +209,11 @@ fun AppNavigationHost(
) { navBackStackEntry -> ) { navBackStackEntry ->
val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!! val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.SeasonListView.withArgs(id)
SeasonListScreen(id = id, appNavController = appNavController) SeasonListScreen(id = id, appNavController = appNavController)
} }
composable( composable(
route = AppNavItem.CaseCrewListView.route.plus("/{${NavConstants.TYPE_KEY}}/{${NavConstants.ID_KEY}}"), route = AppNavItem.CastCrewListView.route.plus("/{${NavConstants.TYPE_KEY}}/{${NavConstants.ID_KEY}}"),
arguments = listOf( arguments = listOf(
navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) }, navArgument(NavConstants.TYPE_KEY) { type = NavType.EnumType(MediaViewType::class.java) },
navArgument(NavConstants.ID_KEY) { type = NavType.IntType } navArgument(NavConstants.ID_KEY) { type = NavType.IntType }
@@ -208,6 +222,7 @@ fun AppNavigationHost(
val type = navBackStackEntry.arguments?.safeGetSerializable(NavConstants.TYPE_KEY, MediaViewType::class.java)!! val type = navBackStackEntry.arguments?.safeGetSerializable(NavConstants.TYPE_KEY, MediaViewType::class.java)!!
val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!! val id = navBackStackEntry.arguments?.getInt(NavConstants.ID_KEY)!!
applicationViewModel.currentRoute.value = AppNavItem.CastCrewListView.withArgs(type, id)
CastCrewListScreen(appNavController = appNavController, type = type, id = id) CastCrewListScreen(appNavController = appNavController, type = type, id = id)
} }
} }
@@ -244,7 +259,7 @@ sealed class AppNavItem(val route: String) {
object SeasonListView: AppNavItem("season_list_route") { object SeasonListView: AppNavItem("season_list_route") {
fun withArgs(id: Int) = route.plus("/$id") fun withArgs(id: Int) = route.plus("/$id")
} }
object CaseCrewListView: AppNavItem("cast_crew_list_route") { object CastCrewListView: AppNavItem("cast_crew_list_route") {
fun withArgs(type: MediaViewType, id: Int) = route.plus("/$type/$id") fun withArgs(type: MediaViewType, id: Int) = route.plus("/$type/$id")
} }

View File

@@ -18,15 +18,12 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.Description
import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -52,6 +49,8 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.owenlejeune.tvtime.BuildConfig import com.owenlejeune.tvtime.BuildConfig
import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.TVTLargeTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.utils.FileUtils import com.owenlejeune.tvtime.utils.FileUtils
import dev.jeziellago.compose.markdowntext.MarkdownText import dev.jeziellago.compose.markdowntext.MarkdownText
@@ -73,17 +72,11 @@ fun AboutScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(connection = scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(connection = scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
LargeTopAppBar( TVTLargeTopAppBar(
title = { Text(text = stringResource(id = R.string.nav_about_title)) }, title = { Text(text = stringResource(id = R.string.nav_about_title)) },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null
)
}
} }
) )
} }

View File

@@ -2,8 +2,6 @@ package com.owenlejeune.tvtime.ui.screens
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@@ -37,9 +35,11 @@ import com.owenlejeune.tvtime.extensions.getCalendarYear
import com.owenlejeune.tvtime.extensions.lazyPagingItems import com.owenlejeune.tvtime.extensions.lazyPagingItems
import com.owenlejeune.tvtime.extensions.unlessEmpty import com.owenlejeune.tvtime.extensions.unlessEmpty
import com.owenlejeune.tvtime.ui.components.AccountIcon import com.owenlejeune.tvtime.ui.components.AccountIcon
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.MediaResultCard
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
import com.owenlejeune.tvtime.ui.components.ScrollableTabs import com.owenlejeune.tvtime.ui.components.ScrollableTabs
import com.owenlejeune.tvtime.ui.components.TVTLargeTopAppBar
import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.navigation.AppNavItem
import com.owenlejeune.tvtime.ui.screens.tabs.AccountTabNavItem import com.owenlejeune.tvtime.ui.screens.tabs.AccountTabNavItem
import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel
@@ -70,17 +70,11 @@ fun AccountScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
LargeTopAppBar( TVTLargeTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(navController = appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
Icons.Filled.ArrowBack,
contentDescription = null
)
}
}, },
title = { title = {
if (currentSession?.isAuthorized == false) { if (currentSession?.isAuthorized == false) {
@@ -90,7 +84,6 @@ fun AccountScreen(
Text(text = getAccountName(accountDetails.value)) Text(text = getAccountName(accountDetails.value))
} }
}, },
colors = TopAppBarDefaults.largeTopAppBarColors(scrolledContainerColor = MaterialTheme.colorScheme.background),
actions = { actions = {
var showDropDownMenu by remember { mutableStateOf(false) } var showDropDownMenu by remember { mutableStateOf(false) }
AccountIcon( AccountIcon(

View File

@@ -5,15 +5,10 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -31,8 +26,10 @@ import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCastMember import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCastMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCastMember import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCastMember
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.MediaResultCard
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
@@ -59,22 +56,12 @@ fun CastCrewListScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = details?.title ?: "") }, title = { Text(text = details?.title ?: "") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton(onClick = { appNavController.popBackStack() }) { BackButton(navController = appNavController)
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }

View File

@@ -8,27 +8,23 @@ import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.PosterItem import com.owenlejeune.tvtime.ui.components.PosterItem
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
@@ -51,22 +47,12 @@ fun GalleryView(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = "Images") }, title = { Text(text = "Images") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton(onClick = { appNavController.popBackStack() }) { BackButton(navController = appNavController)
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }

View File

@@ -13,7 +13,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
@@ -46,6 +45,7 @@ import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.AccountIcon import com.owenlejeune.tvtime.ui.components.AccountIcon
import com.owenlejeune.tvtime.ui.components.ProfileMenuContainer import com.owenlejeune.tvtime.ui.components.ProfileMenuContainer
import com.owenlejeune.tvtime.ui.components.ProfileMenuDefaults import com.owenlejeune.tvtime.ui.components.ProfileMenuDefaults
import com.owenlejeune.tvtime.ui.components.TVTLargeTopAppBar
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavHost import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavHost
import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavItem import com.owenlejeune.tvtime.ui.navigation.HomeScreenNavItem
import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel
@@ -88,7 +88,8 @@ fun HomeScreen(
if (windowSize != WindowSizeClass.Expanded) { if (windowSize != WindowSizeClass.Expanded) {
TopBar( TopBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
navigationIcon = navigationIcon navigationIcon = navigationIcon,
appNavController = appNavController
) )
} }
}, },
@@ -119,6 +120,7 @@ fun HomeScreen(
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TopBar( private fun TopBar(
appNavController: NavController,
scrollBehavior: TopAppBarScrollBehavior, scrollBehavior: TopAppBarScrollBehavior,
navigationIcon: @Composable () -> Unit = {} navigationIcon: @Composable () -> Unit = {}
) { ) {
@@ -126,13 +128,10 @@ private fun TopBar(
val title = remember { homeScreenViewModel.appBarTitle } val title = remember { homeScreenViewModel.appBarTitle }
val actions = remember { homeScreenViewModel.appBarActions } val actions = remember { homeScreenViewModel.appBarActions }
LargeTopAppBar( TVTLargeTopAppBar(
title = { Text(text = title.value) }, title = { Text(text = title.value) },
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults appNavController = appNavController,
.largeTopAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background
),
actions = actions.value, actions = actions.value,
navigationIcon = navigationIcon navigationIcon = navigationIcon
) )
@@ -251,7 +250,8 @@ private fun DualColumnMainContent(
Column { Column {
TopBar( TopBar(
scrollBehavior = topBarScrollBehaviour, scrollBehavior = topBarScrollBehaviour,
navigationIcon = navigationIcon navigationIcon = navigationIcon,
appNavController = appNavController
) )
MainMediaView( MainMediaView(
appNavController = appNavController, appNavController = appNavController,

View File

@@ -4,28 +4,23 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.capitalize import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.extensions.lazyPagingItems import com.owenlejeune.tvtime.extensions.lazyPagingItems
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.MediaResultCard
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
import com.owenlejeune.tvtime.utils.types.MediaViewType import com.owenlejeune.tvtime.utils.types.MediaViewType
@@ -46,17 +41,11 @@ fun KeywordResultsScreen(
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
title = { Text(text = keyword.capitalize(Locale.current)) }, title = { Text(text = keyword.capitalize(Locale.current)) },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(navController = appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null
)
}
} }
) )
} }

View File

@@ -6,15 +6,10 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -34,8 +29,10 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCast
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCast import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCast
import com.owenlejeune.tvtime.extensions.bringToFront import com.owenlejeune.tvtime.extensions.bringToFront
import com.owenlejeune.tvtime.extensions.getCalendarYear import com.owenlejeune.tvtime.extensions.getCalendarYear
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.MediaResultCard
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
@@ -61,22 +58,12 @@ fun KnownForScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = person?.name ?: "") }, title = { Text(text = person?.name ?: "") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton(onClick = { appNavController.popBackStack() }) { BackButton(navController = appNavController)
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }

View File

@@ -9,7 +9,6 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@@ -41,9 +40,11 @@ import com.owenlejeune.tvtime.extensions.WindowSizeClass
import com.owenlejeune.tvtime.extensions.unlessEmpty import com.owenlejeune.tvtime.extensions.unlessEmpty
import com.owenlejeune.tvtime.ui.components.Actions import com.owenlejeune.tvtime.ui.components.Actions
import com.owenlejeune.tvtime.ui.components.ActionsView import com.owenlejeune.tvtime.ui.components.ActionsView
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.RatingView import com.owenlejeune.tvtime.ui.components.RatingView
import com.owenlejeune.tvtime.ui.components.Spinner import com.owenlejeune.tvtime.ui.components.Spinner
import com.owenlejeune.tvtime.ui.components.SwitchPreference import com.owenlejeune.tvtime.ui.components.SwitchPreference
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.navigation.AppNavItem
import com.owenlejeune.tvtime.ui.theme.* import com.owenlejeune.tvtime.ui.theme.*
import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel
@@ -59,9 +60,7 @@ import kotlin.math.roundToInt
@Composable @Composable
fun ListDetailScreen( fun ListDetailScreen(
appNavController: NavController, appNavController: NavController,
itemId: Int, itemId: Int
windowSize: WindowSizeClass,
service: ListV4Service = KoinJavaComponent.get(ListV4Service::class.java)
) { ) {
val accountViewModel = viewModel<AccountViewModel>() val accountViewModel = viewModel<AccountViewModel>()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
@@ -81,24 +80,12 @@ fun ListDetailScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = parentList?.name ?: "") }, title = { Text(text = parentList?.name ?: "") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(navController = appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }
@@ -148,7 +135,7 @@ private fun ListHeader(
val url = TmdbUtils.getAccountGravatarUrl(list.createdBy.gravatarHash) val url = TmdbUtils.getAccountGravatarUrl(list.createdBy.gravatarHash)
val model = ImageRequest.Builder(LocalContext.current) val model = ImageRequest.Builder(LocalContext.current)
.data(url) .data(url)
.diskCacheKey(url ?: "") .diskCacheKey(url)
.networkCachePolicy(CachePolicy.ENABLED) .networkCachePolicy(CachePolicy.ENABLED)
.memoryCachePolicy(CachePolicy.ENABLED) .memoryCachePolicy(CachePolicy.ENABLED)
.build() .build()

View File

@@ -27,7 +27,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons 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.Movie
import androidx.compose.material.icons.filled.Send import androidx.compose.material.icons.filled.Send
import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.PullRefreshIndicator
@@ -37,12 +36,9 @@ import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -98,6 +94,7 @@ import com.owenlejeune.tvtime.extensions.listItems
import com.owenlejeune.tvtime.preferences.AppPreferences import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.ActionsView import com.owenlejeune.tvtime.ui.components.ActionsView
import com.owenlejeune.tvtime.ui.components.AvatarImage import com.owenlejeune.tvtime.ui.components.AvatarImage
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.ChipDefaults import com.owenlejeune.tvtime.ui.components.ChipDefaults
import com.owenlejeune.tvtime.ui.components.ChipGroup import com.owenlejeune.tvtime.ui.components.ChipGroup
import com.owenlejeune.tvtime.ui.components.ChipInfo import com.owenlejeune.tvtime.ui.components.ChipInfo
@@ -115,6 +112,7 @@ import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
import com.owenlejeune.tvtime.ui.components.PosterItem import com.owenlejeune.tvtime.ui.components.PosterItem
import com.owenlejeune.tvtime.ui.components.RoundedChip import com.owenlejeune.tvtime.ui.components.RoundedChip
import com.owenlejeune.tvtime.ui.components.RoundedTextField import com.owenlejeune.tvtime.ui.components.RoundedTextField
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard
import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.navigation.AppNavItem
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
@@ -211,24 +209,12 @@ fun MediaDetailScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = mediaItem?.title ?: "") }, title = { Text(text = mediaItem?.title ?: "") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(navController = appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }
@@ -349,7 +335,6 @@ private fun MediaViewContent(
if (type == MediaViewType.TV) { if (type == MediaViewType.TV) {
SeasonCard( SeasonCard(
itemId = itemId, itemId = itemId,
mediaItem = mediaItem,
mainViewModel = mainViewModel, mainViewModel = mainViewModel,
appNavController = appNavController appNavController = appNavController
) )
@@ -751,7 +736,7 @@ private fun CastCard(
.padding(start = 12.dp, bottom = 12.dp) .padding(start = 12.dp, bottom = 12.dp)
.clickable { .clickable {
appNavController.navigate( appNavController.navigate(
AppNavItem.CaseCrewListView.withArgs( AppNavItem.CastCrewListView.withArgs(
type, type,
itemId itemId
) )
@@ -798,7 +783,6 @@ private fun CastCrewCard(appNavController: NavController, person: Person) {
@Composable @Composable
private fun SeasonCard( private fun SeasonCard(
itemId: Int, itemId: Int,
mediaItem: DetailedItem?,
mainViewModel: MainViewModel, mainViewModel: MainViewModel,
appNavController: NavController appNavController: NavController
) { ) {
@@ -1077,7 +1061,7 @@ private fun WatchProviderContainer(
val url = TmdbUtils.fullLogoPath(item.logoPath) val url = TmdbUtils.fullLogoPath(item.logoPath)
val model = ImageRequest.Builder(LocalContext.current) val model = ImageRequest.Builder(LocalContext.current)
.data(url) .data(url)
.diskCacheKey(url ?: "") .diskCacheKey(url)
.networkCachePolicy(CachePolicy.ENABLED) .networkCachePolicy(CachePolicy.ENABLED)
.memoryCachePolicy(CachePolicy.ENABLED) .memoryCachePolicy(CachePolicy.ENABLED)
.build() .build()
@@ -1120,18 +1104,19 @@ private fun NextMcuProjectCard(
shape = RoundedCornerShape(10.dp), shape = RoundedCornerShape(10.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 10.dp), elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
modifier = modifier.then(Modifier modifier = modifier.then(
.fillMaxWidth() Modifier
.clickable { .fillMaxWidth()
nextMcuProject.value?.let { .clickable {
appNavController.navigate( nextMcuProject.value?.let {
AppNavItem.DetailView.withArgs( appNavController.navigate(
it.type, AppNavItem.DetailView.withArgs(
it.id it.type,
it.id
)
) )
) }
} }
}
) )
) { ) {
Box( Box(

View File

@@ -16,18 +16,14 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -47,11 +43,13 @@ import androidx.navigation.NavController
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailPerson import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailPerson
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.ContentCard import com.owenlejeune.tvtime.ui.components.ContentCard
import com.owenlejeune.tvtime.ui.components.DetailHeader import com.owenlejeune.tvtime.ui.components.DetailHeader
import com.owenlejeune.tvtime.ui.components.ExpandableContentCard import com.owenlejeune.tvtime.ui.components.ExpandableContentCard
import com.owenlejeune.tvtime.ui.components.ExternalIdsArea import com.owenlejeune.tvtime.ui.components.ExternalIdsArea
import com.owenlejeune.tvtime.ui.components.PosterItem import com.owenlejeune.tvtime.ui.components.PosterItem
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard
import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.navigation.AppNavItem
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
@@ -111,22 +109,12 @@ fun PersonDetailScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { Text(text = person?.name ?: "") }, title = { Text(text = person?.name ?: "") },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton(onClick = { appNavController.popBackStack() }) { BackButton(navController = appNavController)
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }

View File

@@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Clear import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@@ -30,8 +29,10 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.* import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
import com.owenlejeune.tvtime.extensions.getCalendarYear import com.owenlejeune.tvtime.extensions.getCalendarYear
import com.owenlejeune.tvtime.extensions.lazyPagingItems import com.owenlejeune.tvtime.extensions.lazyPagingItems
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.MediaResultCard
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.ui.viewmodel.SearchViewModel import com.owenlejeune.tvtime.ui.viewmodel.SearchViewModel
@@ -70,7 +71,8 @@ fun SearchScreen(
} }
} }
TopAppBar( TVTTopAppBar(
appNavController = appNavController,
title = { title = {
TextField( TextField(
value = searchValue.value, value = searchValue.value,
@@ -96,12 +98,7 @@ fun SearchScreen(
) )
}, },
navigationIcon = { navigationIcon = {
IconButton(onClick = { appNavController.popBackStack() }) { BackButton(navController = appNavController)
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button)
)
}
} }
) )
Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant) Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant)

View File

@@ -23,17 +23,14 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.ExpandMore import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -52,7 +49,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -62,9 +58,10 @@ import androidx.navigation.NavController
import coil.compose.AsyncImage import coil.compose.AsyncImage
import coil.request.CachePolicy import coil.request.CachePolicy
import coil.request.ImageRequest import coil.request.ImageRequest
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Episode import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Episode
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Season import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Season
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
@@ -94,24 +91,12 @@ fun SeasonListScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TVTTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
),
title = { }, title = { },
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( BackButton(navController = appNavController)
onClick = { appNavController.popBackStack() }
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.content_description_back_button),
tint = MaterialTheme.colorScheme.primary
)
}
} }
) )
} }

View File

@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
@@ -29,10 +30,10 @@ import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.outlined.DarkMode import androidx.compose.material.icons.outlined.DarkMode
import androidx.compose.material.icons.outlined.Flare import androidx.compose.material.icons.outlined.Flare
import androidx.compose.material.icons.outlined.LightMode import androidx.compose.material.icons.outlined.LightMode
import androidx.compose.material.icons.outlined.Restore
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -64,6 +65,7 @@ import com.kieronquinn.monetcompat.core.MonetCompat
import com.owenlejeune.tvtime.BuildConfig import com.owenlejeune.tvtime.BuildConfig
import com.owenlejeune.tvtime.OnboardingActivity import com.owenlejeune.tvtime.OnboardingActivity
import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.extensions.unlessEmpty
import com.owenlejeune.tvtime.preferences.AppPreferences import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.CenteredIconCircle import com.owenlejeune.tvtime.ui.components.CenteredIconCircle
import com.owenlejeune.tvtime.ui.components.PaletteView import com.owenlejeune.tvtime.ui.components.PaletteView
@@ -71,6 +73,7 @@ import com.owenlejeune.tvtime.ui.components.PreferenceHeading
import com.owenlejeune.tvtime.ui.components.RadioButtonPreference import com.owenlejeune.tvtime.ui.components.RadioButtonPreference
import com.owenlejeune.tvtime.ui.components.SliderPreference import com.owenlejeune.tvtime.ui.components.SliderPreference
import com.owenlejeune.tvtime.ui.components.SwitchPreference import com.owenlejeune.tvtime.ui.components.SwitchPreference
import com.owenlejeune.tvtime.ui.components.TVTLargeTopAppBar
import com.owenlejeune.tvtime.ui.navigation.SettingsNavItem import com.owenlejeune.tvtime.ui.navigation.SettingsNavItem
import com.owenlejeune.tvtime.ui.navigation.SettingsNavigationHost import com.owenlejeune.tvtime.ui.navigation.SettingsNavigationHost
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
@@ -98,12 +101,9 @@ fun SettingsScreen(
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
LargeTopAppBar( TVTLargeTopAppBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults appNavController = appNavController,
.largeTopAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background
),
title = { Text(text = appBarTitle.value) }, title = { Text(text = appBarTitle.value) },
navigationIcon = { navigationIcon = {
IconButton( IconButton(
@@ -516,6 +516,28 @@ fun DevPreferences() {
} }
) )
) )
val applicationViewModel = viewModel<ApplicationViewModel>()
val currentStoredRoute = remember { applicationViewModel.storedRoute }
Row(
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(text = "Current stored test route", fontSize = 18.sp)
Text(text = currentStoredRoute.value.unlessEmpty("---"))
}
Spacer(modifier = Modifier.weight(1f))
IconButton(
onClick = {
applicationViewModel.setStoredRoute("")
}
) {
Icon(
imageVector = Icons.Outlined.Restore,
contentDescription = null
)
}
}
} }
} }
} }

View File

@@ -16,7 +16,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
@@ -24,6 +23,7 @@ import androidx.navigation.NavController
import com.google.accompanist.web.AccompanistWebViewClient import com.google.accompanist.web.AccompanistWebViewClient
import com.google.accompanist.web.WebView import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState import com.google.accompanist.web.rememberWebViewState
import com.owenlejeune.tvtime.ui.components.TVTTopAppBar
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.utils.SessionManager import com.owenlejeune.tvtime.utils.SessionManager
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
@@ -41,8 +41,9 @@ fun WebLinkScreen(
Scaffold( Scaffold(
topBar = { topBar = {
SmallTopAppBar( TVTTopAppBar(
title = {}, title = {},
appNavController = appNavController,
navigationIcon = { navigationIcon = {
IconButton( IconButton(
onClick = { onClick = {

View File

@@ -3,15 +3,29 @@ package com.owenlejeune.tvtime.ui.viewmodel
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.owenlejeune.tvtime.preferences.AppPreferences
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class ApplicationViewModel: ViewModel() { class ApplicationViewModel: ViewModel(), KoinComponent {
private val preferences: AppPreferences by inject()
private object Backer { private object Backer {
val statusBarColor = mutableStateOf(Color.Transparent) val statusBarColor = mutableStateOf(Color.Transparent)
val navigationBarColor = mutableStateOf(Color.Transparent) val navigationBarColor = mutableStateOf(Color.Transparent)
val currentRoute = mutableStateOf("")
val storedRoute = mutableStateOf("")
} }
val statusBarColor = Backer.statusBarColor val statusBarColor = Backer.statusBarColor
val navigationBarColor = Backer.navigationBarColor val navigationBarColor = Backer.navigationBarColor
val currentRoute = Backer.currentRoute
val storedRoute = Backer.storedRoute
fun setStoredRoute(route: String) {
storedRoute.value = route
preferences.storedTestRoute = route
}
} }