mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-23 04:00:53 -05:00
redesign settings pages
This commit is contained in:
@@ -4,10 +4,11 @@ import android.os.Bundle
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.animation.rememberSplineBasedDecay
|
import androidx.compose.animation.rememberSplineBasedDecay
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Scaffold
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
@@ -30,7 +31,6 @@ import androidx.navigation.compose.composable
|
|||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import androidx.navigation.navArgument
|
import androidx.navigation.navArgument
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|
||||||
import com.kieronquinn.monetcompat.app.MonetCompatActivity
|
import com.kieronquinn.monetcompat.app.MonetCompatActivity
|
||||||
import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
import com.owenlejeune.tvtime.extensions.WindowSizeClass
|
||||||
import com.owenlejeune.tvtime.extensions.rememberWindowSizeClass
|
import com.owenlejeune.tvtime.extensions.rememberWindowSizeClass
|
||||||
@@ -40,9 +40,7 @@ import com.owenlejeune.tvtime.ui.components.SearchFab
|
|||||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavGraph
|
import com.owenlejeune.tvtime.ui.navigation.MainNavGraph
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaDetailView
|
import com.owenlejeune.tvtime.ui.screens.main.*
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.PersonDetailView
|
|
||||||
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
|
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
|
||||||
import com.owenlejeune.tvtime.utils.KeyboardManager
|
import com.owenlejeune.tvtime.utils.KeyboardManager
|
||||||
import com.owenlejeune.tvtime.utils.SessionManager
|
import com.owenlejeune.tvtime.utils.SessionManager
|
||||||
@@ -115,6 +113,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
topBar = {
|
topBar = {
|
||||||
if (windowSize != WindowSizeClass.Expanded) {
|
if (windowSize != WindowSizeClass.Expanded) {
|
||||||
TopBar(
|
TopBar(
|
||||||
|
appNavController = appNavController,
|
||||||
title = appBarTitle,
|
title = appBarTitle,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
appBarActions = appBarActions
|
appBarActions = appBarActions
|
||||||
@@ -151,19 +150,31 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(
|
private fun TopBar(
|
||||||
|
appNavController: NavHostController,
|
||||||
title: MutableState<String>,
|
title: MutableState<String>,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({})
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({})
|
||||||
) {
|
) {
|
||||||
|
val defaultAppBarActions: @Composable RowScope.() -> Unit = {
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
appNavController.navigate(MainNavItem.SettingsView.route)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(imageVector = Icons.Filled.Settings, contentDescription = stringResource(id = R.string.nav_settings_title))
|
||||||
|
}
|
||||||
|
}
|
||||||
LargeTopAppBar(
|
LargeTopAppBar(
|
||||||
title = { Text(text = title.value) },
|
title = { Text(text = title.value) },
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
colors = TopAppBarDefaults
|
colors = TopAppBarDefaults
|
||||||
.largeTopAppBarColors(
|
.largeTopAppBarColors(
|
||||||
scrolledContainerColor = MaterialTheme.colorScheme.background,
|
scrolledContainerColor = MaterialTheme.colorScheme.background
|
||||||
titleContentColor = MaterialTheme.colorScheme.primary
|
|
||||||
),
|
),
|
||||||
actions = appBarActions.value
|
actions = {
|
||||||
|
defaultAppBarActions()
|
||||||
|
appBarActions.value(this)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +327,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
TopBar(
|
TopBar(
|
||||||
|
appNavController = appNavController,
|
||||||
title = appBarTitle,
|
title = appBarTitle,
|
||||||
scrollBehavior = topBarScrollBehaviour,
|
scrollBehavior = topBarScrollBehaviour,
|
||||||
appBarActions = appBarActions
|
appBarActions = appBarActions
|
||||||
@@ -365,12 +377,13 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
private object NavConstants {
|
private object NavConstants {
|
||||||
const val ID_KEY = "id_key"
|
const val ID_KEY = "id_key"
|
||||||
const val TYPE_KEY = "type_key"
|
const val TYPE_KEY = "type_key"
|
||||||
|
const val SETTINGS_KEY = "settings_key"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainNavigationRoutes(
|
private fun MainNavigationRoutes(
|
||||||
startDestination: String = MainNavItem.MainView.route,
|
startDestination: String = MainNavItem.MainView.route,
|
||||||
mainNavStartRoute: String = BottomNavItem.Items[0].route,
|
mainNavStartRoute: String = MainNavItem.Items[0].route,
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
) {
|
) {
|
||||||
NavHost(navController = appNavController, startDestination = startDestination) {
|
NavHost(navController = appNavController, startDestination = startDestination) {
|
||||||
@@ -399,6 +412,22 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class AppPreferences(context: Context) {
|
|||||||
private val USE_V4_API = "use_v4_api"
|
private val USE_V4_API = "use_v4_api"
|
||||||
private val SHOW_BACKDROP_GALLERY = "show_backdrop_gallery"
|
private val SHOW_BACKDROP_GALLERY = "show_backdrop_gallery"
|
||||||
private val USE_WALLPAPER_COLORS = "use_wallpaper_colors"
|
private val USE_WALLPAPER_COLORS = "use_wallpaper_colors"
|
||||||
|
private val DARK_THEME = "dark_theme"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
|
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
|
||||||
@@ -46,6 +47,10 @@ class AppPreferences(context: Context) {
|
|||||||
|
|
||||||
|
|
||||||
/******* Design Preferences ********/
|
/******* Design Preferences ********/
|
||||||
|
var darkTheme: Int
|
||||||
|
get() = preferences.getInt(DARK_THEME, 0)
|
||||||
|
set(value) { preferences.put(DARK_THEME, value) }
|
||||||
|
|
||||||
var useSystemColors: Boolean
|
var useSystemColors: Boolean
|
||||||
get() = preferences.getBoolean(USE_SYSTEM_COLORS, true)
|
get() = preferences.getBoolean(USE_SYSTEM_COLORS, true)
|
||||||
set(value) { preferences.put(USE_SYSTEM_COLORS, value) }
|
set(value) { preferences.put(USE_SYSTEM_COLORS, value) }
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package com.owenlejeune.tvtime.ui.components
|
package com.owenlejeune.tvtime.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material3.SliderDefaults
|
import androidx.compose.foundation.selection.selectable
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.Slider
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import androidx.compose.ui.semantics.role
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -92,7 +96,9 @@ fun SliderPreference(
|
|||||||
var sliderValue by remember { mutableStateOf(value) }
|
var sliderValue by remember { mutableStateOf(value) }
|
||||||
|
|
||||||
Slider(
|
Slider(
|
||||||
modifier = Modifier.fillMaxWidth().padding(start = 8.dp),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 8.dp),
|
||||||
value = sliderValue,
|
value = sliderValue,
|
||||||
onValueChange = { sliderValue = it },
|
onValueChange = { sliderValue = it },
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
@@ -107,3 +113,59 @@ fun SliderPreference(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun RadioButtonPreference(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
selected: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
title: String,
|
||||||
|
icon: ImageVector,
|
||||||
|
titleTextColor: Color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
disabledTextColor: Color = MaterialTheme.colorScheme.outline
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
// modifier = modifier
|
||||||
|
// .clickable(
|
||||||
|
// enabled = enabled,
|
||||||
|
// onClick = onClick
|
||||||
|
// )
|
||||||
|
// .semantics { role = Role.RadioButton }
|
||||||
|
modifier = modifier
|
||||||
|
.padding(all = 8.dp)
|
||||||
|
.selectable(
|
||||||
|
selected = selected,
|
||||||
|
onClick = onClick,
|
||||||
|
role = Role.RadioButton
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.padding(end = 16.dp),
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = title,
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
|
||||||
|
val titleColor = if (enabled) titleTextColor else disabledTextColor
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically),
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
color = titleColor,
|
||||||
|
fontSize = 20.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
RadioButton(
|
||||||
|
modifier = Modifier.align(Alignment.CenterVertically),
|
||||||
|
selected = selected,
|
||||||
|
onClick = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import androidx.compose.material.OutlinedTextField
|
|||||||
import androidx.compose.material.TextFieldDefaults
|
import androidx.compose.material.TextFieldDefaults
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
|
import androidx.compose.material.icons.outlined.ArrowDropDown
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
@@ -75,6 +76,7 @@ import kotlinx.coroutines.launch
|
|||||||
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
||||||
import org.intellij.markdown.html.HtmlGenerator
|
import org.intellij.markdown.html.HtmlGenerator
|
||||||
import org.intellij.markdown.parser.MarkdownParser
|
import org.intellij.markdown.parser.MarkdownParser
|
||||||
|
import kotlin.math.exp
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopLevelSwitch(
|
fun TopLevelSwitch(
|
||||||
@@ -960,3 +962,51 @@ fun CenteredIconCircle(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> Spinner(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
list: List<Pair<String, T>>,
|
||||||
|
preselected: Pair<String, T>,
|
||||||
|
onSelectionChanged: (Pair<String, T>) -> Unit
|
||||||
|
) {
|
||||||
|
var selected by remember { mutableStateOf(preselected) }
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Box(modifier = modifier) {
|
||||||
|
Column {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = selected.first,
|
||||||
|
onValueChange = { },
|
||||||
|
trailingIcon = { Icon(Icons.Outlined.ArrowDropDown, null) },
|
||||||
|
readOnly = true,
|
||||||
|
modifier = Modifier.clickable(
|
||||||
|
onClick = {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
list.forEach { entry ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = entry.first) },
|
||||||
|
onClick = {
|
||||||
|
selected = entry
|
||||||
|
expanded = false
|
||||||
|
onSelectionChanged(selected)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
fun SpinnerPreview() {
|
||||||
|
Spinner(list = listOf("T" to "T", "Q" to "Q", "F" to "F"), modifier = Modifier.width(300.dp), preselected = "T" to "T", onSelectionChanged = {})
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ sealed class BottomNavItem(stringRes: Int, val icon: Int, val route: String): Ko
|
|||||||
val name = resourceUtils.getString(stringRes)
|
val name = resourceUtils.getString(stringRes)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val Items by lazy { listOf(Movies, TV, People, Account, Settings) }
|
val Items by lazy { listOf(Movies, TV, People, Account) }
|
||||||
val SearchableRoutes by lazy { listOf(Movies.route, TV.route, People.route) }
|
val SearchableRoutes by lazy { listOf(Movies.route, TV.route, People.route) }
|
||||||
|
|
||||||
fun getByRoute(route: String?): BottomNavItem? {
|
fun getByRoute(route: String?): BottomNavItem? {
|
||||||
@@ -20,8 +20,7 @@ sealed class BottomNavItem(stringRes: Int, val icon: Int, val route: String): Ko
|
|||||||
Movies.route -> Movies
|
Movies.route -> Movies
|
||||||
TV.route -> TV
|
TV.route -> TV
|
||||||
Account.route -> Account
|
Account.route -> Account
|
||||||
// Favourites.route -> Favourites
|
Favourites.route -> Favourites
|
||||||
Settings.route -> Settings
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,8 +29,7 @@ sealed class BottomNavItem(stringRes: Int, val icon: Int, val route: String): Ko
|
|||||||
object Movies: BottomNavItem(R.string.nav_movies_title, R.drawable.ic_movie, "movies_route")
|
object Movies: BottomNavItem(R.string.nav_movies_title, R.drawable.ic_movie, "movies_route")
|
||||||
object TV: BottomNavItem(R.string.nav_tv_title, R.drawable.ic_tv, "tv_route")
|
object TV: BottomNavItem(R.string.nav_tv_title, R.drawable.ic_tv, "tv_route")
|
||||||
object Account: BottomNavItem(R.string.nav_account_title, R.drawable.ic_person, "account_route")
|
object Account: BottomNavItem(R.string.nav_account_title, R.drawable.ic_person, "account_route")
|
||||||
// object Favourites: BottomNavItem(R.string.nav_favourites_title, R.drawable.ic_favorite, "favourites_route")
|
object Favourites: BottomNavItem(R.string.nav_favourites_title, R.drawable.ic_favorite, "favourites_route")
|
||||||
object Settings: BottomNavItem(R.string.nav_settings_title, R.drawable.ic_settings, "settings_route")
|
|
||||||
object People: BottomNavItem(R.string.nav_people_title, R.drawable.ic_face, "people_route")
|
object People: BottomNavItem(R.string.nav_people_title, R.drawable.ic_face, "people_route")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ package com.owenlejeune.tvtime.ui.navigation
|
|||||||
|
|
||||||
sealed class MainNavItem(val route: String) {
|
sealed class MainNavItem(val route: String) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val Items = listOf(MainView, DetailView, SettingsView)
|
||||||
|
}
|
||||||
|
|
||||||
object MainView: MainNavItem("main_route")
|
object MainView: MainNavItem("main_route")
|
||||||
object DetailView: MainNavItem("detail_route")
|
object DetailView: MainNavItem("detail_route")
|
||||||
|
object SettingsView: MainNavItem("settings_route")
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,13 +44,9 @@ fun MainNavGraph(
|
|||||||
appBarActions.value = {}
|
appBarActions.value = {}
|
||||||
PeopleTab(appBarTitle = appBarTitle, appNavController = appNavController)
|
PeopleTab(appBarTitle = appBarTitle, appNavController = appNavController)
|
||||||
}
|
}
|
||||||
// composable(BottomNavItem.Favourites.route) {
|
composable(BottomNavItem.Favourites.route) {
|
||||||
// appBarActions.value = {}
|
|
||||||
// FavouritesTab()
|
|
||||||
// }
|
|
||||||
composable(BottomNavItem.Settings.route) {
|
|
||||||
appBarActions.value = {}
|
appBarActions.value = {}
|
||||||
SettingsTab(appBarTitle = appBarTitle, activity = activity)
|
FavouritesTab()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AccountCircle
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -289,7 +290,8 @@ private fun AccountDropdownMenu(
|
|||||||
IconButton(
|
IconButton(
|
||||||
onClick = { expanded.value = true }
|
onClick = { expanded.value = true }
|
||||||
) {
|
) {
|
||||||
Icon(imageVector = Icons.Filled.MoreVert, contentDescription = null)
|
// Icon(imageVector = Icons.Filled.MoreVert, contentDescription = null)
|
||||||
|
Icon(imageVector = Icons.Filled.AccountCircle, contentDescription = stringResource(id = R.string.nav_account_title))
|
||||||
}
|
}
|
||||||
|
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.owenlejeune.tvtime.ui.screens.main
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.compose.animation.rememberSplineBasedDecay
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
@@ -12,9 +13,9 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.TextButton
|
import androidx.compose.material.TextButton
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material.icons.filled.ResetTv
|
import androidx.compose.material.icons.outlined.DarkMode
|
||||||
import androidx.compose.material.icons.filled.RestartAlt
|
import androidx.compose.material.icons.outlined.LightMode
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
@@ -22,43 +23,179 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||||
import com.owenlejeune.tvtime.BuildConfig
|
import com.owenlejeune.tvtime.BuildConfig
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||||
import com.owenlejeune.tvtime.ui.components.*
|
import com.owenlejeune.tvtime.ui.components.*
|
||||||
|
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||||
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
|
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||||
import com.owenlejeune.tvtime.utils.SessionManager
|
import com.owenlejeune.tvtime.utils.SessionManager
|
||||||
import dev.kdrag0n.monet.factory.ColorSchemeFactory
|
import dev.kdrag0n.monet.factory.ColorSchemeFactory
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
import org.koin.java.KoinJavaComponent.get
|
import org.koin.java.KoinJavaComponent.get
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsTab(
|
fun SettingsTab(
|
||||||
appBarTitle: MutableState<String>,
|
appNavController: NavController,
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
|
route: String? = null,
|
||||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
) {
|
) {
|
||||||
appBarTitle.value = stringResource(id = R.string.nav_settings_title)
|
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||||
|
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||||
|
val scrollBehavior = remember(decayAnimationSpec) {
|
||||||
|
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||||
|
}
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val appBarTitle = remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
topBar = {
|
||||||
|
LargeTopAppBar(
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
colors = TopAppBarDefaults
|
||||||
|
.largeTopAppBarColors(
|
||||||
|
scrolledContainerColor = MaterialTheme.colorScheme.background
|
||||||
|
),
|
||||||
|
title = { Text(text = appBarTitle.value) },
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { appNavController.popBackStack() }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = stringResource(id = R.string.content_description_back_button)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Box(modifier = Modifier.padding(innerPadding)) {
|
||||||
|
if (route != null) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(all = 24.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
|
) {
|
||||||
|
SettingsPage.getByRoute(route).apply {
|
||||||
|
appBarTitle.value = name
|
||||||
|
SettingsPageRenderer(appNavController, activity, preferences)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SettingsTabView(
|
||||||
|
appNavController = appNavController,
|
||||||
|
appBarTitle = appBarTitle
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SettingsTabView(
|
||||||
|
appNavController: NavController,
|
||||||
|
appBarTitle: MutableState<String>
|
||||||
|
) {
|
||||||
|
appBarTitle.value = stringResource(id = R.string.nav_settings_title)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
.padding(all = 24.dp),
|
||||||
.verticalScroll(scrollState)
|
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
) {
|
) {
|
||||||
/******* Search Preferences ********/
|
TopLevelSettingsCard(
|
||||||
PreferenceHeading(text = stringResource(R.string.preference_heading_search))
|
title = stringResource(id = R.string.preference_heading_search),
|
||||||
|
subtitle = stringResource(R.string.preference_subtitle_search),
|
||||||
|
icon = Icons.Filled.Search,
|
||||||
|
settingsView = SettingsPage.SearchSettings,
|
||||||
|
appNavController = appNavController
|
||||||
|
)
|
||||||
|
|
||||||
|
TopLevelSettingsCard(
|
||||||
|
title = stringResource(id = R.string.preference_heading_design),
|
||||||
|
subtitle = stringResource(R.string.preference_subtitle_design),
|
||||||
|
icon = Icons.Filled.Palette,
|
||||||
|
settingsView = SettingsPage.DesignSettings,
|
||||||
|
appNavController = appNavController
|
||||||
|
)
|
||||||
|
|
||||||
|
TopLevelSettingsCard(
|
||||||
|
title = stringResource(id = R.string.preferences_debug_title),
|
||||||
|
subtitle = stringResource(R.string.preference_subtitle_debug),
|
||||||
|
icon = Icons.Filled.DeveloperBoard,
|
||||||
|
settingsView = SettingsPage.DeveloperSettings,
|
||||||
|
appNavController = appNavController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TopLevelSettingsCard(
|
||||||
|
title: String,
|
||||||
|
subtitle: String? = null,
|
||||||
|
icon: ImageVector,
|
||||||
|
settingsView: SettingsPage,
|
||||||
|
appNavController: NavController
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
.clickable(
|
||||||
|
onClick = {
|
||||||
|
appNavController.navigate("${MainNavItem.SettingsView.route}/${settingsView.route}")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = subtitle,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.padding(end = 16.dp),
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
val titleColor = MaterialTheme.colorScheme.onBackground
|
||||||
|
val subtitleColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
Text(text = title, style = MaterialTheme.typography.titleLarge, color = titleColor, fontSize = 20.sp)
|
||||||
|
subtitle?.let {
|
||||||
|
Text(text = subtitle, style = MaterialTheme.typography.bodyMedium, color = subtitleColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SearchPreferences(
|
||||||
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
|
) {
|
||||||
val persistentSearch = remember { mutableStateOf(preferences.persistentSearch) }
|
val persistentSearch = remember { mutableStateOf(preferences.persistentSearch) }
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
titleText = stringResource(R.string.preferences_persistent_search_title),
|
titleText = stringResource(R.string.preferences_persistent_search_title),
|
||||||
@@ -81,9 +218,21 @@ fun SettingsTab(
|
|||||||
},
|
},
|
||||||
enabled = persistentSearch.value
|
enabled = persistentSearch.value
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/******* Design Preferences ********/
|
@Composable
|
||||||
PreferenceHeading(text = stringResource(id = R.string.preference_heading_design))
|
private fun DesignPreferences(
|
||||||
|
appNavController: NavController,
|
||||||
|
activity: AppCompatActivity,
|
||||||
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
|
) {
|
||||||
|
TopLevelSettingsCard(
|
||||||
|
title = stringResource(id = R.string.preference_heading_dark_mode),
|
||||||
|
subtitle = stringResource(R.string.preference_subtitle_dark_mode),
|
||||||
|
icon = Icons.Outlined.DarkMode,
|
||||||
|
settingsView = SettingsPage.DarkModeSettings,
|
||||||
|
appNavController = appNavController
|
||||||
|
)
|
||||||
|
|
||||||
val useWallpaperColors = remember { mutableStateOf(preferences.useWallpaperColors) }
|
val useWallpaperColors = remember { mutableStateOf(preferences.useWallpaperColors) }
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
@@ -124,11 +273,14 @@ fun SettingsTab(
|
|||||||
}
|
}
|
||||||
MonetCompat.getInstance().updateMonetColors()
|
MonetCompat.getInstance().updateMonetColors()
|
||||||
},
|
},
|
||||||
enabled = (if (isSystemColorsSupported) !preferences.useSystemColors else true).and(useWallpaperColors.value)
|
enabled = (if (isSystemColorsSupported) !preferences.useSystemColors else true).and(
|
||||||
|
useWallpaperColors.value
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val showWallpaperPicker = remember { mutableStateOf(false) }
|
val showWallpaperPicker = remember { mutableStateOf(false) }
|
||||||
val wallpaperPickerModifier = if (isSystemColorsSupported && preferences.useSystemColors && useWallpaperColors.value) {
|
val wallpaperPickerModifier =
|
||||||
|
if (isSystemColorsSupported && preferences.useSystemColors && useWallpaperColors.value) {
|
||||||
Modifier
|
Modifier
|
||||||
} else {
|
} else {
|
||||||
Modifier.clickable { showWallpaperPicker.value = true }
|
Modifier.clickable { showWallpaperPicker.value = true }
|
||||||
@@ -148,18 +300,140 @@ fun SettingsTab(
|
|||||||
if (showWallpaperPicker.value) {
|
if (showWallpaperPicker.value) {
|
||||||
WallpaperPicker(showPopup = showWallpaperPicker)
|
WallpaperPicker(showPopup = showWallpaperPicker)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******* Dev Preferences ********/
|
enum class DarkMode {
|
||||||
if (BuildConfig.DEBUG) {
|
Automatic,
|
||||||
Divider(modifier = Modifier.padding(start = 8.dp, top = 20.dp), color = MaterialTheme.colorScheme.primaryContainer)
|
Dark,
|
||||||
Text(
|
Light
|
||||||
modifier = Modifier.padding(start = 8.dp, top = 20.dp),
|
}
|
||||||
text = stringResource(R.string.preferences_debug_title),
|
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
@Composable
|
||||||
color = MaterialTheme.colorScheme.primary
|
private fun DarkModePreferences(
|
||||||
)
|
activity: AppCompatActivity,
|
||||||
DebugOptions()
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
|
) {
|
||||||
|
val selectedValue = remember { mutableStateOf(preferences.darkTheme) }
|
||||||
|
|
||||||
|
val isSelected: (Int) -> Boolean = { selectedValue.value == it }
|
||||||
|
val onChangeState: (Int) -> Unit = {
|
||||||
|
selectedValue.value = it
|
||||||
|
preferences.darkTheme = it
|
||||||
|
activity.recreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreferenceHeading(text = "Automatic")
|
||||||
|
RadioButtonPreference(
|
||||||
|
selected = isSelected(DarkMode.Automatic.ordinal),
|
||||||
|
title = "Follow system",
|
||||||
|
icon = Icons.Filled.Brightness6,
|
||||||
|
onClick = {
|
||||||
|
onChangeState(DarkMode.Automatic.ordinal)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
PreferenceHeading(text = "Manual")
|
||||||
|
RadioButtonPreference(
|
||||||
|
selected = isSelected(DarkMode.Light.ordinal),
|
||||||
|
title = "Light mode",
|
||||||
|
icon = Icons.Outlined.LightMode,
|
||||||
|
onClick = {
|
||||||
|
onChangeState(DarkMode.Light.ordinal)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
RadioButtonPreference(
|
||||||
|
selected = isSelected(DarkMode.Dark.ordinal),
|
||||||
|
title = "Dark mode",
|
||||||
|
icon = Icons.Outlined.DarkMode,
|
||||||
|
onClick = {
|
||||||
|
onChangeState(DarkMode.Dark.ordinal)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DevPreferences(
|
||||||
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
|
) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val firstLaunchTesting = remember { mutableStateOf(preferences.firstLaunchTesting) }
|
||||||
|
SwitchPreference(
|
||||||
|
titleText = "Always show onboarding flow",
|
||||||
|
subtitleText = "Show onboarding flow on each launch",
|
||||||
|
checkState = firstLaunchTesting.value,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
firstLaunchTesting.value = isChecked
|
||||||
|
preferences.firstLaunchTesting = isChecked
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val shouldShowPalette = remember { mutableStateOf(false) }
|
||||||
|
Text(
|
||||||
|
text = "Show material palette",
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||||
|
.clickable(
|
||||||
|
onClick = {
|
||||||
|
shouldShowPalette.value = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (shouldShowPalette.value) {
|
||||||
|
AlertDialog(
|
||||||
|
modifier = Modifier.padding(12.dp),
|
||||||
|
title = { Text(text = "Palette") },
|
||||||
|
text = { PaletteView() },
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = { shouldShowPalette.value = false }) {
|
||||||
|
Text("Dismiss")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {},
|
||||||
|
onDismissRequest = { shouldShowPalette.value = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Clear session",
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||||
|
.clickable(
|
||||||
|
onClick = {
|
||||||
|
preferences.guestSessionId = ""
|
||||||
|
coroutineScope.launch {
|
||||||
|
SessionManager.clearSession {
|
||||||
|
Toast
|
||||||
|
.makeText(context, "Cleared session: $it", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
SessionManager.clearSessionV4 {
|
||||||
|
Toast
|
||||||
|
.makeText(
|
||||||
|
context,
|
||||||
|
"Cleared session v4: $it",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val useV4Api = remember { mutableStateOf(preferences.useV4Api) }
|
||||||
|
SwitchPreference(
|
||||||
|
titleText = "Use v4 API",
|
||||||
|
checkState = useV4Api.value,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
useV4Api.value = isChecked
|
||||||
|
preferences.useV4Api = isChecked
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,80 +516,24 @@ private fun WallpaperPicker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
private sealed class SettingsPage(stringRes: Int, val route: String, val SettingsPageRenderer: @Composable (NavController, AppCompatActivity, AppPreferences) -> Unit): KoinComponent {
|
||||||
private fun DebugOptions(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
private val resources: ResourceUtils by inject()
|
||||||
val context = LocalContext.current
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val firstLaunchTesting = remember { mutableStateOf(preferences.firstLaunchTesting) }
|
val name = resources.getString(stringRes)
|
||||||
SwitchPreference(
|
|
||||||
titleText = "Always show onboarding flow",
|
|
||||||
subtitleText = "Show onboarding flow on each launch",
|
|
||||||
checkState = firstLaunchTesting.value,
|
|
||||||
onCheckedChange = { isChecked ->
|
|
||||||
firstLaunchTesting.value = isChecked
|
|
||||||
preferences.firstLaunchTesting = isChecked
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val shouldShowPalette = remember { mutableStateOf(false) }
|
companion object {
|
||||||
Text(
|
val Pages by lazy {listOf(SearchSettings, DesignSettings, DeveloperSettings, DarkModeSettings) }
|
||||||
text = "Show material palette",
|
|
||||||
color = MaterialTheme.colorScheme.onBackground,
|
fun getByRoute(route: String): SettingsPage {
|
||||||
modifier = Modifier
|
return Pages.map { it.route to it }
|
||||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
.find { it.first == route }
|
||||||
.clickable(
|
?.second
|
||||||
onClick = {
|
?: throw IllegalArgumentException("Invalid settings page route: $route")
|
||||||
shouldShowPalette.value = true
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
)
|
|
||||||
if (shouldShowPalette.value) {
|
|
||||||
AlertDialog(
|
|
||||||
modifier = Modifier.padding(12.dp),
|
|
||||||
title = { Text(text = "Palette") },
|
|
||||||
text = { PaletteView() },
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = { shouldShowPalette.value = false }) {
|
|
||||||
Text("Dismiss")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
confirmButton = {},
|
|
||||||
onDismissRequest = { shouldShowPalette.value = false }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
object SearchSettings: SettingsPage(R.string.preference_heading_search, "search", @Composable { n, a, p -> SearchPreferences(p) } )
|
||||||
text = "Clear session",
|
object DesignSettings: SettingsPage(R.string.preference_heading_design, "design", @Composable { n, a, p -> DesignPreferences(n, a, p) } )
|
||||||
color = MaterialTheme.colorScheme.onBackground,
|
object DeveloperSettings: SettingsPage(R.string.preferences_debug_title,"dev", @Composable { n, a, p -> DevPreferences(p) } )
|
||||||
modifier = Modifier
|
object DarkModeSettings: SettingsPage(R.string.preference_heading_dark_mode, "darkmode", @Composable { n, a, p -> DarkModePreferences(a, p) } )
|
||||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
|
||||||
.clickable(
|
|
||||||
onClick = {
|
|
||||||
preferences.guestSessionId = ""
|
|
||||||
coroutineScope.launch {
|
|
||||||
SessionManager.clearSession {
|
|
||||||
Toast
|
|
||||||
.makeText(context, "Cleared session: $it", Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
SessionManager.clearSessionV4 {
|
|
||||||
Toast
|
|
||||||
.makeText(context, "Cleared session v4: $it", Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val useV4Api = remember { mutableStateOf(preferences.useV4Api) }
|
|
||||||
SwitchPreference(
|
|
||||||
titleText = "Use v4 API",
|
|
||||||
checkState = useV4Api.value,
|
|
||||||
onCheckedChange = { isChecked ->
|
|
||||||
useV4Api.value = isChecked
|
|
||||||
preferences.useV4Api = isChecked
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||||
|
import com.owenlejeune.tvtime.ui.screens.main.DarkMode
|
||||||
import org.koin.java.KoinJavaComponent.get
|
import org.koin.java.KoinJavaComponent.get
|
||||||
|
|
||||||
private val DarkColorPalette = darkColorScheme(
|
private val DarkColorPalette = darkColorScheme(
|
||||||
@@ -69,46 +70,19 @@ private val LightColorPalette = lightColorScheme(
|
|||||||
inverseOnSurface = N1_50
|
inverseOnSurface = N1_50
|
||||||
)
|
)
|
||||||
|
|
||||||
//@Composable
|
|
||||||
//fun TVTimeTheme(
|
|
||||||
// isDarkTheme: Boolean = isSystemInDarkTheme(),
|
|
||||||
// isDynamicColor: Boolean = true,
|
|
||||||
// content: @Composable () -> Unit
|
|
||||||
//) {
|
|
||||||
// val dynamicColor = isDynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
|
||||||
// val colorScheme = when {
|
|
||||||
// dynamicColor && isDarkTheme -> {
|
|
||||||
// dynamicDarkColorScheme(LocalContext.current)
|
|
||||||
// }
|
|
||||||
// dynamicColor && !isDarkTheme -> {
|
|
||||||
// dynamicLightColorScheme(LocalContext.current)
|
|
||||||
// }
|
|
||||||
// isDarkTheme -> DarkColorPalette
|
|
||||||
// else -> LightColorPalette
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val systemUiController = rememberSystemUiController()
|
|
||||||
// systemUiController.setSystemBarsColor(colorScheme.background, !isDarkTheme)
|
|
||||||
//
|
|
||||||
// MaterialTheme(
|
|
||||||
// colorScheme = colorScheme,
|
|
||||||
// typography = Typography,
|
|
||||||
// content = content
|
|
||||||
// )
|
|
||||||
//}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TVTimeTheme(
|
fun TVTimeTheme(
|
||||||
preferences: AppPreferences = get(AppPreferences::class.java),
|
preferences: AppPreferences = get(AppPreferences::class.java),
|
||||||
isDarkTheme: Boolean = isSystemInDarkTheme(),
|
|
||||||
monetCompat: MonetCompat,
|
monetCompat: MonetCompat,
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
// val colors = if(isDarkTheme) {
|
val isDarkTheme = when(preferences.darkTheme) {
|
||||||
// monetCompat.darkMonetCompatScheme()
|
DarkMode.Automatic.ordinal -> isSystemInDarkTheme()
|
||||||
// } else {
|
DarkMode.Dark.ordinal -> true
|
||||||
// monetCompat.lightMonetCompatScheme()
|
DarkMode.Light.ordinal -> false
|
||||||
// }
|
else -> throw IllegalArgumentException("Illegal theme value ${preferences.darkTheme}")
|
||||||
|
}
|
||||||
|
|
||||||
val colors = when {
|
val colors = when {
|
||||||
isDarkTheme && preferences.useWallpaperColors -> monetCompat.darkMonetCompatScheme()
|
isDarkTheme && preferences.useWallpaperColors -> monetCompat.darkMonetCompatScheme()
|
||||||
isDarkTheme && !preferences.useWallpaperColors -> DarkColorPalette
|
isDarkTheme && !preferences.useWallpaperColors -> DarkColorPalette
|
||||||
|
|||||||
@@ -117,4 +117,9 @@
|
|||||||
<string name="preferences_use_wallpaper_colors_title">Use wallpaper colors</string>
|
<string name="preferences_use_wallpaper_colors_title">Use wallpaper colors</string>
|
||||||
<string name="preferences_use_wallpaper_colors_subtitle">Use theme colors pulled from your device\'s wallpaper</string>
|
<string name="preferences_use_wallpaper_colors_subtitle">Use theme colors pulled from your device\'s wallpaper</string>
|
||||||
<string name="preference_system_colors_subtitle">Use wallpaper colors chosen by your device</string>
|
<string name="preference_system_colors_subtitle">Use wallpaper colors chosen by your device</string>
|
||||||
|
<string name="preference_subtitle_search">Search bar view settings</string>
|
||||||
|
<string name="preference_subtitle_design">Design and theming options</string>
|
||||||
|
<string name="preference_subtitle_debug">Secret developer options</string>
|
||||||
|
<string name="preference_heading_dark_mode">Dark mode</string>
|
||||||
|
<string name="preference_subtitle_dark_mode">Light, dark, or auto</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user