add in options for showing/hiding search bar and page heading

This commit is contained in:
Owen LeJeune
2022-02-18 14:34:52 -05:00
parent 399795cb54
commit 0da9f01551
8 changed files with 391 additions and 88 deletions

View File

@@ -8,15 +8,24 @@ class AppPreferences(context: Context) {
companion object { companion object {
private val PREF_FILE = "tvtime_shared_preferences" private val PREF_FILE = "tvtime_shared_preferences"
private val USE_PREFERENCES = "use_android_12_colors" // private val USE_PREFERENCES = "use_android_12_colors"
private val PERSISTENT_SEARCH = "persistent_search"
private val HIDE_TITLE = "hide_title"
} }
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE) private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
var persistentSearch: Boolean
get() = preferences.getBoolean(PERSISTENT_SEARCH, true)
set(value) { preferences.put(PERSISTENT_SEARCH, value) }
var hideTitle: Boolean
get() = preferences.getBoolean(HIDE_TITLE, false)
set(value) { preferences.put(HIDE_TITLE, value) }
// val usePreferences: MutableState<Boolean> // val usePreferences: MutableState<Boolean>
var usePreferences: Boolean // var usePreferences: Boolean
get() = preferences.getBoolean(USE_PREFERENCES, false) // get() = preferences.getBoolean(USE_PREFERENCES, false)
set(value) { preferences.put(USE_PREFERENCES, value) } // set(value) { preferences.put(USE_PREFERENCES, value) }
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,76 @@
package com.owenlejeune.tvtime.ui.components
import androidx.compose.foundation.layout.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun PreferenceHeading(
text: String,
modifier: Modifier = Modifier
) {
Text(
modifier = modifier
.padding(8.dp),
text = text,
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.bodyMedium
)
}
@Composable
fun SwitchPreference(
titleText: String,
checkState: Boolean,
modifier: Modifier = Modifier,
subtitleText: String = "",
onCheckedChange: (Boolean) -> Unit = {},
titleTextColor: Color = MaterialTheme.colorScheme.onBackground,
subtitleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
disabledTextColor: Color = MaterialTheme.colorScheme.outline,
enabled: Boolean = true
) {
Row(
modifier = modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 8.dp)
) {
Column(
modifier = Modifier
.align(Alignment.CenterVertically)
.weight(1f)
) {
val titleColor = if (enabled) titleTextColor else disabledTextColor
val subtitleColor = if (enabled) subtitleTextColor else disabledTextColor
Text(text = titleText, style = MaterialTheme.typography.titleLarge, color = titleColor, fontSize = 20.sp)
if (subtitleText.isNotEmpty()) {
Text(text = subtitleText, style = MaterialTheme.typography.bodyMedium, color = subtitleColor)
}
}
CustomSwitch(
modifier = Modifier
.align(Alignment.CenterVertically),
checked = checkState,
onCheckedChange = onCheckedChange,
width = 30.dp,
height = 15.dp,
colors = CustomSwitchColors.standardColors(),
enabled = enabled
)
}
}
@Preview
@Composable
private fun SwitchPreferencePreview() {
SwitchPreference("Title", true, subtitleText = "Subtitle")
}

View File

@@ -13,6 +13,8 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Card import androidx.compose.material.Card
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Switch
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.* import androidx.compose.material3.*
@@ -27,6 +29,7 @@ import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
@@ -39,6 +42,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
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.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@@ -82,8 +86,8 @@ fun TopLevelSwitch(
) )
CustomSwitch( CustomSwitch(
modifier = Modifier.padding(40.dp, 12.dp), modifier = Modifier.padding(40.dp, 12.dp),
switchState = checkedState, checked = checkedState.value,
onCheckChanged = { isChecked -> onCheckedChange = { isChecked ->
checkedState.value = isChecked checkedState.value = isChecked
onCheckChanged(isChecked) onCheckChanged(isChecked)
} }
@@ -92,29 +96,144 @@ fun TopLevelSwitch(
} }
} }
@Composable class CustomSwitchColors private constructor(
private fun CustomSwitch( val lightUncheckedTrackColor: Color,
modifier: Modifier = Modifier, val darkUncheckedTrackColor: Color,
switchState: MutableState<Boolean> = remember { mutableStateOf(false) }, val lightUncheckedThumbColor: Color,
onCheckChanged: (Boolean) -> Unit = {} val darkUncheckedThumbColor: Color,
val lightCheckedTrackColor: Color,
val darkCheckedTrackColor: Color,
val lightCheckedThumbColor: Color,
val darkCheckedThumbColor: Color,
val lightDisabledTrackColor: Color,
val darkDisabledTrackColor: Color,
val lightDisabledThumbColor: Color,
val darkDisabledThumbColor: Color
){ ){
val width = 30.dp companion object {
val height = 15.dp @Composable
fun topLevelColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color =MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
@Composable
fun standardColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.secondaryContainer,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
}
}
@Composable
fun CustomSwitch(
modifier: Modifier = Modifier,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit = {},
width: Dp = 30.dp,
height: Dp = 15.dp,
colors: CustomSwitchColors = CustomSwitchColors.topLevelColors(),
enabled: Boolean = true
) {
val checkedState = remember { mutableStateOf(checked) }
val gapBetweenThumbAndTrackEdge = 2.dp val gapBetweenThumbAndTrackEdge = 2.dp
val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge
val animatePosition = animateFloatAsState( val animatePosition = animateFloatAsState(
targetValue = if (switchState.value) { targetValue = if (checkedState.value) {
with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() } with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() }
} else { } else {
with (LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() } with (LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() }
} }
) )
val uncheckedTrackColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.surfaceVariant else MaterialTheme.colorScheme.outline val uncheckedTrackColor = if (enabled) {
val uncheckedThumbColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.outline else MaterialTheme.colorScheme.surfaceVariant if (isSystemInDarkTheme()) colors.darkUncheckedTrackColor else colors.lightUncheckedTrackColor
val checkedTrackColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.outline else MaterialTheme.colorScheme.primary } else {
val checkedThumbColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer if (isSystemInDarkTheme()) colors.darkDisabledTrackColor else colors.lightDisabledTrackColor
}
val uncheckedThumbColor = if (enabled) {
if (isSystemInDarkTheme()) colors.darkUncheckedThumbColor else colors.lightUncheckedThumbColor
} else {
if (isSystemInDarkTheme()) colors.darkDisabledThumbColor else colors.lightDisabledThumbColor
}
val checkedTrackColor = if (enabled) {
if (isSystemInDarkTheme()) colors.darkCheckedTrackColor else colors.lightCheckedTrackColor
} else {
if (isSystemInDarkTheme()) colors.darkDisabledTrackColor else colors.lightDisabledTrackColor
}
val checkedThumbColor = if (enabled) {
if (isSystemInDarkTheme()) colors.darkCheckedThumbColor else colors.lightCheckedThumbColor
} else {
if (isSystemInDarkTheme()) colors.darkDisabledThumbColor else colors.lightDisabledThumbColor
}
Canvas( Canvas(
modifier = modifier modifier = modifier
@@ -123,18 +242,18 @@ private fun CustomSwitch(
.pointerInput(Unit) { .pointerInput(Unit) {
detectTapGestures( detectTapGestures(
onTap = { onTap = {
switchState.value = !switchState.value checkedState.value = !checkedState.value
onCheckChanged(switchState.value) onCheckedChange(checkedState.value)
} }
) )
} }
) { ) {
drawRoundRect( drawRoundRect(
color = if (switchState.value) checkedTrackColor else uncheckedTrackColor, color = if (checkedState.value) checkedTrackColor else uncheckedTrackColor,
cornerRadius = CornerRadius(x = 10.dp.toPx(), y = 10.dp.toPx()) cornerRadius = CornerRadius(x = 10.dp.toPx(), y = 10.dp.toPx())
) )
drawCircle( drawCircle(
color = if (switchState.value) checkedThumbColor else uncheckedThumbColor, color = if (checkedState.value) checkedThumbColor else uncheckedThumbColor,
radius = thumbRadius.toPx(), radius = thumbRadius.toPx(),
center = Offset( center = Offset(
x = animatePosition.value, x = animatePosition.value,

View File

@@ -48,24 +48,19 @@ fun MainNavigationRoutes(navController: NavHostController, displayUnderStatusBar
@Composable @Composable
fun BottomNavigationRoutes( fun BottomNavigationRoutes(
appNavController: NavHostController, appNavController: NavHostController,
navController: NavHostController, navController: NavHostController
shouldShowSearch: MutableState<Boolean>
) { ) {
NavHost(navController = navController, startDestination = BottomNavItem.Movies.route) { NavHost(navController = navController, startDestination = BottomNavItem.Movies.route) {
composable(BottomNavItem.Movies.route) { composable(BottomNavItem.Movies.route) {
shouldShowSearch.value = true
MediaTab(appNavController = appNavController, mediaType = MediaViewType.MOVIE) MediaTab(appNavController = appNavController, mediaType = MediaViewType.MOVIE)
} }
composable(BottomNavItem.TV.route) { composable(BottomNavItem.TV.route) {
shouldShowSearch.value = true
MediaTab(appNavController = appNavController, mediaType = MediaViewType.TV) MediaTab(appNavController = appNavController, mediaType = MediaViewType.TV)
} }
composable(BottomNavItem.Favourites.route) { composable(BottomNavItem.Favourites.route) {
shouldShowSearch.value = false
FavouritesTab() FavouritesTab()
} }
composable(BottomNavItem.Settings.route) { composable(BottomNavItem.Settings.route) {
shouldShowSearch.value = false
SettingsTab() SettingsTab()
} }
} }

View File

@@ -1,7 +1,10 @@
package com.owenlejeune.tvtime.ui.screens package com.owenlejeune.tvtime.ui.screens
import androidx.compose.animation.rememberSplineBasedDecay import androidx.compose.animation.rememberSplineBasedDecay
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@@ -16,14 +19,16 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.RoundedTextField import com.owenlejeune.tvtime.ui.components.RoundedTextField
import com.owenlejeune.tvtime.ui.components.SearchFab 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.BottomNavigationRoutes import com.owenlejeune.tvtime.ui.navigation.BottomNavigationRoutes
import org.koin.java.KoinJavaComponent.get
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
@Composable @Composable
fun MainAppView(appNavController: NavHostController) { fun MainAppView(appNavController: NavHostController, preferences: AppPreferences = get(AppPreferences::class.java)) {
val navController = rememberNavController() val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState() val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route val currentRoute = navBackStackEntry?.destination?.route
@@ -34,7 +39,8 @@ fun MainAppView(appNavController: NavHostController) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec) TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
} }
val shouldShowSearch = remember { mutableStateOf(true) } val shouldShowSearch = remember { mutableStateOf(false) }
val searchableScreens = listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)
// todo - scroll state not remember when returing from detail screen // todo - scroll state not remember when returing from detail screen
@@ -48,47 +54,71 @@ fun MainAppView(appNavController: NavHostController) {
) )
}, },
topBar = { topBar = {
TopBar( if (currentRoute in searchableScreens) {
SearchTopBar(
title = appBarTitle, title = appBarTitle,
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
shouldShowSearch = shouldShowSearch shouldShowSearch = shouldShowSearch
) )
} else {
TopBar(
title = appBarTitle,
scrollBehavior = scrollBehavior
)
}
}, },
floatingActionButton = { floatingActionButton = {
if (currentRoute in listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)) { if (currentRoute in searchableScreens && !preferences.persistentSearch) {
SearchFab() SearchFab()
} }
} }
) { innerPadding -> ) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) { Box(modifier = Modifier.padding(innerPadding)) {
BottomNavigationRoutes(appNavController = appNavController, navController = navController, shouldShowSearch = shouldShowSearch) BottomNavigationRoutes(appNavController = appNavController, navController = navController)
} }
} }
} }
@Composable @Composable
private fun TopBar( private fun TopBar(
title: MutableState<String>,
scrollBehavior: TopAppBarScrollBehavior
) {
LargeTopAppBar(
title = { Text(text = title.value) },
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults
.largeTopAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.primary
)
)
}
@Composable
private fun SearchTopBar(
title: MutableState<String>, title: MutableState<String>,
scrollBehavior: TopAppBarScrollBehavior, scrollBehavior: TopAppBarScrollBehavior,
hasSearchFocus: MutableState<Boolean> = remember { mutableStateOf(false) }, hasSearchFocus: MutableState<Boolean> = remember { mutableStateOf(false) },
shouldShowSearch: MutableState<Boolean> = remember { mutableStateOf(true) } shouldShowSearch: MutableState<Boolean> = remember { mutableStateOf(false) },
preferences: AppPreferences = get(AppPreferences::class.java)
) { ) {
SmallTopAppBar( SmallTopAppBar(
title = { title = {
Row( Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
if (!hasSearchFocus.value) { if (!hasSearchFocus.value && !(preferences.persistentSearch && preferences.hideTitle)) {
Text(text = title.value) Text(text = title.value)
} }
if (shouldShowSearch.value) { if (shouldShowSearch.value || preferences.persistentSearch) {
var textState by remember { mutableStateOf("") } var textState by remember { mutableStateOf("") }
val basePadding = 8.dp val basePadding = 8.dp
RoundedTextField( RoundedTextField(
modifier = Modifier modifier = Modifier
.padding( .padding(
end = if (hasSearchFocus.value) (basePadding * 2) else basePadding, end = if (hasSearchFocus.value || preferences.hideTitle) (basePadding * 3) else basePadding,
start = if (hasSearchFocus.value) 0.dp else basePadding start = if (hasSearchFocus.value || preferences.hideTitle) 0.dp else basePadding
) )
.height(35.dp) .height(35.dp)
@@ -97,7 +127,7 @@ private fun TopBar(
}, },
value = textState, value = textState,
onValueChange = { textState = it }, onValueChange = { textState = it },
placeHolder = "Search ${title.value.lowercase()}" placeHolder = "Search ${title.value}"
) )
} }
} }

View File

@@ -1,10 +1,11 @@
package com.owenlejeune.tvtime.ui.screens.tabs.bottom package com.owenlejeune.tvtime.ui.screens.tabs.bottom
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.layout.padding import androidx.compose.material.Switch
import androidx.compose.material.TextButton
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -13,39 +14,90 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
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.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.owenlejeune.tvtime.BuildConfig
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.preferences.AppPreferences import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.PaletteView import com.owenlejeune.tvtime.ui.components.*
import com.owenlejeune.tvtime.ui.components.TopLevelSwitch
import org.koin.java.KoinJavaComponent.get import org.koin.java.KoinJavaComponent.get
@Composable @Composable
fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) { fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
Column(modifier = Modifier.fillMaxSize()) { val scrollState = rememberScrollState()
val usePreferences = remember { mutableStateOf(preferences.usePreferences) }
TopLevelSwitch( Column(modifier = Modifier
text = "Enable Preferences", .fillMaxSize()
checkedState = usePreferences, .padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
onCheckChanged = { isChecked -> .verticalScroll(scrollState)
usePreferences.value = isChecked ) {
preferences.usePreferences = isChecked // val usePreferences = remember { mutableStateOf(preferences.usePreferences) }
// TopLevelSwitch(
// text = "Enable Preferences",
// checkedState = usePreferences,
// onCheckChanged = { isChecked ->
// usePreferences.value = isChecked
// preferences.usePreferences = isChecked
// }
// )
//
// Column(
// modifier = Modifier
// .fillMaxWidth()
// .wrapContentHeight()
// .padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
// .verticalScroll()
// ) {
PreferenceHeading(text = stringResource(R.string.preference_heading_search))
val persistentSearch = remember { mutableStateOf(preferences.persistentSearch) }
SwitchPreference(
titleText = stringResource(R.string.preferences_persistent_search_title),
subtitleText = stringResource(R.string.preferences_persistent_search_subtitle),
checkState = persistentSearch.value,
onCheckedChange = { isChecked ->
persistentSearch.value = isChecked
preferences.persistentSearch = isChecked
} }
) )
val hideTitle = remember { mutableStateOf(preferences.hideTitle) }
SwitchPreference(
titleText = stringResource(R.string.preferences_hide_heading_title),
subtitleText = stringResource(R.string.preferences_hide_heading_subtitle),
checkState = hideTitle.value,
onCheckedChange = { isChecked ->
hideTitle.value = isChecked
preferences.hideTitle = isChecked
},
enabled = persistentSearch.value
)
if (BuildConfig.DEBUG) {
Text(
modifier = Modifier.padding(start = 8.dp, top = 20.dp),
text = stringResource(R.string.preferences_debug_title),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onBackground
)
DebugOptions()
}
}
}
@Composable
private fun DebugOptions() {
val shouldShowPalette = remember { mutableStateOf(false) } val shouldShowPalette = remember { mutableStateOf(false) }
Text( Text(
text = "Show material palette", text = "Show material palette",
color = if (usePreferences.value) { color = MaterialTheme.colorScheme.onBackground,
MaterialTheme.colorScheme.onBackground
} else {
MaterialTheme.colorScheme.outline
},
modifier = Modifier modifier = Modifier
.padding(12.dp) .padding(horizontal = 8.dp, vertical = 12.dp)
.clickable( .clickable(
enabled = usePreferences.value,
onClick = { onClick = {
shouldShowPalette.value = true shouldShowPalette.value = true
} }
@@ -55,24 +107,16 @@ fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
PaletteDialog(shouldShowPalette) PaletteDialog(shouldShowPalette)
} }
} }
}
@Composable @Composable
private fun PaletteDialog(showDialog: MutableState<Boolean>) { private fun PaletteDialog(showDialog: MutableState<Boolean>) {
AlertDialog( AlertDialog(
modifier = Modifier.padding(12.dp), modifier = Modifier.padding(12.dp),
title = { title = { Text(text = "Palette") },
Text(text = "Palette") text = { PaletteView() },
},
text = {
PaletteView()
},
dismissButton = { dismissButton = {
Button( TextButton(onClick = { showDialog.value = false }) {
modifier = Modifier.fillMaxWidth(), Text("Dismiss")
onClick = { showDialog.value = false }
) {
Text(text = "Dismiss", color = Color.White)
} }
}, },
confirmButton = {}, confirmButton = {},

View File

@@ -1,9 +1,27 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">TVTime</string> <string name="app_name">TVTime</string>
<!-- nav -->
<string name="nav_movies_title">Films</string> <string name="nav_movies_title">Films</string>
<string name="nav_tv_title">Télé</string> <string name="nav_tv_title">Télé</string>
<string name="nav_favourites_title">Favoris</string> <string name="nav_favourites_title">Favoris</string>
<string name="nav_settings_title">Réglages</string> <string name="nav_settings_title">Réglages</string>
<string name="nav_now_playing_title">Lecture en cours</string>
<string name="nav_popular_title">Populaire</string>
<string name="nav_top_rated_title">Les mieux notés</string>
<string name="nav_upcoming_title">A venir</string>
<string name="nav_tv_airing_today_title">Aujourd\'hui</string>
<string name="nav_tv_on_the_air">À l\'antenne</string>
<!-- -->
<string name="cast_label">Acteurs</string> <string name="cast_label">Acteurs</string>
<!-- preferences -->
<string name="preference_heading_search">Rechercher</string>
<string name="preferences_persistent_search_title">Barre de recherche presistante</string>
<string name="preferences_persistent_search_subtitle">Gardez la barre de recherche visible à tout moment</string>
<string name="preferences_hide_heading_title">Barre de recherche étendue</string>
<string name="preferences_hide_heading_subtitle">Gardez la barre de recherche développée à tout moment</string>
<string name="preferences_debug_title">Options de développeur</string>
</resources> </resources>

View File

@@ -1,14 +1,26 @@
<resources> <resources>
<string name="app_name">TVTime</string> <string name="app_name">TVTime</string>
<!-- nav -->
<string name="nav_movies_title">Movies</string> <string name="nav_movies_title">Movies</string>
<string name="nav_tv_title">TV</string> <string name="nav_tv_title">TV</string>
<string name="nav_favourites_title">Favourites</string> <string name="nav_favourites_title">Favourites</string>
<string name="nav_settings_title">Settings</string> <string name="nav_settings_title">Settings</string>
<string name="cast_label">Cast</string>
<string name="nav_now_playing_title">Now Playing</string> <string name="nav_now_playing_title">Now Playing</string>
<string name="nav_popular_title">Popular</string> <string name="nav_popular_title">Popular</string>
<string name="nav_top_rated_title">Top Rated</string> <string name="nav_top_rated_title">Top Rated</string>
<string name="nav_upcoming_title">Upcoming</string> <string name="nav_upcoming_title">Upcoming</string>
<string name="nav_tv_airing_today_title">Airing Today</string> <string name="nav_tv_airing_today_title">Airing Today</string>
<string name="nav_tv_on_the_air">On The Air</string> <string name="nav_tv_on_the_air">On The Air</string>
<!-- -->
<string name="cast_label">Cast</string>
<!-- preferences -->
<string name="preference_heading_search">Search</string>
<string name="preferences_persistent_search_title">Persistent search bar</string>
<string name="preferences_persistent_search_subtitle">Keep search bar visible at all times</string>
<string name="preferences_hide_heading_title">Expanded search bar</string>
<string name="preferences_hide_heading_subtitle">Keep search bar expanded at all times</string>
<string name="preferences_debug_title">Developer options</string>
</resources> </resources>