mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-10 05:42:43 -05:00
add in options for showing/hiding search bar and page heading
This commit is contained in:
@@ -8,15 +8,24 @@ class AppPreferences(context: Context) {
|
||||
companion object {
|
||||
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)
|
||||
|
||||
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>
|
||||
var usePreferences: Boolean
|
||||
get() = preferences.getBoolean(USE_PREFERENCES, false)
|
||||
set(value) { preferences.put(USE_PREFERENCES, value) }
|
||||
// var usePreferences: Boolean
|
||||
// get() = preferences.getBoolean(USE_PREFERENCES, false)
|
||||
// set(value) { preferences.put(USE_PREFERENCES, value) }
|
||||
|
||||
private fun SharedPreferences.put(key: String, value: Any?) {
|
||||
edit().apply {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
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.filled.Search
|
||||
import androidx.compose.material3.*
|
||||
@@ -27,6 +29,7 @@ import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
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.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -82,8 +86,8 @@ fun TopLevelSwitch(
|
||||
)
|
||||
CustomSwitch(
|
||||
modifier = Modifier.padding(40.dp, 12.dp),
|
||||
switchState = checkedState,
|
||||
onCheckChanged = { isChecked ->
|
||||
checked = checkedState.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
checkedState.value = isChecked
|
||||
onCheckChanged(isChecked)
|
||||
}
|
||||
@@ -92,29 +96,144 @@ fun TopLevelSwitch(
|
||||
}
|
||||
}
|
||||
|
||||
class CustomSwitchColors private constructor(
|
||||
val lightUncheckedTrackColor: Color,
|
||||
val darkUncheckedTrackColor: Color,
|
||||
val lightUncheckedThumbColor: Color,
|
||||
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
|
||||
){
|
||||
companion object {
|
||||
@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
|
||||
private fun CustomSwitch(
|
||||
fun CustomSwitch(
|
||||
modifier: Modifier = Modifier,
|
||||
switchState: MutableState<Boolean> = remember { mutableStateOf(false) },
|
||||
onCheckChanged: (Boolean) -> Unit = {}
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
width: Dp = 30.dp,
|
||||
height: Dp = 15.dp,
|
||||
colors: CustomSwitchColors = CustomSwitchColors.topLevelColors(),
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
val width = 30.dp
|
||||
val height = 15.dp
|
||||
val checkedState = remember { mutableStateOf(checked) }
|
||||
|
||||
val gapBetweenThumbAndTrackEdge = 2.dp
|
||||
|
||||
val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge
|
||||
val animatePosition = animateFloatAsState(
|
||||
targetValue = if (switchState.value) {
|
||||
targetValue = if (checkedState.value) {
|
||||
with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() }
|
||||
} else {
|
||||
with (LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() }
|
||||
}
|
||||
)
|
||||
|
||||
val uncheckedTrackColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.surfaceVariant else MaterialTheme.colorScheme.outline
|
||||
val uncheckedThumbColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.outline else MaterialTheme.colorScheme.surfaceVariant
|
||||
val checkedTrackColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.outline else MaterialTheme.colorScheme.primary
|
||||
val checkedThumbColor = if (isSystemInDarkTheme()) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer
|
||||
val uncheckedTrackColor = if (enabled) {
|
||||
if (isSystemInDarkTheme()) colors.darkUncheckedTrackColor else colors.lightUncheckedTrackColor
|
||||
} else {
|
||||
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(
|
||||
modifier = modifier
|
||||
@@ -123,18 +242,18 @@ private fun CustomSwitch(
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onTap = {
|
||||
switchState.value = !switchState.value
|
||||
onCheckChanged(switchState.value)
|
||||
checkedState.value = !checkedState.value
|
||||
onCheckedChange(checkedState.value)
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
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())
|
||||
)
|
||||
drawCircle(
|
||||
color = if (switchState.value) checkedThumbColor else uncheckedThumbColor,
|
||||
color = if (checkedState.value) checkedThumbColor else uncheckedThumbColor,
|
||||
radius = thumbRadius.toPx(),
|
||||
center = Offset(
|
||||
x = animatePosition.value,
|
||||
|
||||
@@ -48,24 +48,19 @@ fun MainNavigationRoutes(navController: NavHostController, displayUnderStatusBar
|
||||
@Composable
|
||||
fun BottomNavigationRoutes(
|
||||
appNavController: NavHostController,
|
||||
navController: NavHostController,
|
||||
shouldShowSearch: MutableState<Boolean>
|
||||
navController: NavHostController
|
||||
) {
|
||||
NavHost(navController = navController, startDestination = BottomNavItem.Movies.route) {
|
||||
composable(BottomNavItem.Movies.route) {
|
||||
shouldShowSearch.value = true
|
||||
MediaTab(appNavController = appNavController, mediaType = MediaViewType.MOVIE)
|
||||
}
|
||||
composable(BottomNavItem.TV.route) {
|
||||
shouldShowSearch.value = true
|
||||
MediaTab(appNavController = appNavController, mediaType = MediaViewType.TV)
|
||||
}
|
||||
composable(BottomNavItem.Favourites.route) {
|
||||
shouldShowSearch.value = false
|
||||
FavouritesTab()
|
||||
}
|
||||
composable(BottomNavItem.Settings.route) {
|
||||
shouldShowSearch.value = false
|
||||
SettingsTab()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
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.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
@@ -16,14 +19,16 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
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.SearchFab
|
||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavigationRoutes
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun MainAppView(appNavController: NavHostController) {
|
||||
fun MainAppView(appNavController: NavHostController, preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
val navController = rememberNavController()
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
@@ -34,7 +39,8 @@ fun MainAppView(appNavController: NavHostController) {
|
||||
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
|
||||
|
||||
@@ -48,47 +54,71 @@ fun MainAppView(appNavController: NavHostController) {
|
||||
)
|
||||
},
|
||||
topBar = {
|
||||
TopBar(
|
||||
title = appBarTitle,
|
||||
scrollBehavior = scrollBehavior,
|
||||
shouldShowSearch = shouldShowSearch
|
||||
)
|
||||
if (currentRoute in searchableScreens) {
|
||||
SearchTopBar(
|
||||
title = appBarTitle,
|
||||
scrollBehavior = scrollBehavior,
|
||||
shouldShowSearch = shouldShowSearch
|
||||
)
|
||||
} else {
|
||||
TopBar(
|
||||
title = appBarTitle,
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
if (currentRoute in listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)) {
|
||||
if (currentRoute in searchableScreens && !preferences.persistentSearch) {
|
||||
SearchFab()
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
BottomNavigationRoutes(appNavController = appNavController, navController = navController, shouldShowSearch = shouldShowSearch)
|
||||
BottomNavigationRoutes(appNavController = appNavController, navController = navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
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>,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
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(
|
||||
title = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (!hasSearchFocus.value) {
|
||||
if (!hasSearchFocus.value && !(preferences.persistentSearch && preferences.hideTitle)) {
|
||||
Text(text = title.value)
|
||||
}
|
||||
if (shouldShowSearch.value) {
|
||||
if (shouldShowSearch.value || preferences.persistentSearch) {
|
||||
var textState by remember { mutableStateOf("") }
|
||||
val basePadding = 8.dp
|
||||
RoundedTextField(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
end = if (hasSearchFocus.value) (basePadding * 2) else basePadding,
|
||||
start = if (hasSearchFocus.value) 0.dp else basePadding
|
||||
end = if (hasSearchFocus.value || preferences.hideTitle) (basePadding * 3) else basePadding,
|
||||
start = if (hasSearchFocus.value || preferences.hideTitle) 0.dp else basePadding
|
||||
)
|
||||
|
||||
.height(35.dp)
|
||||
@@ -97,7 +127,7 @@ private fun TopBar(
|
||||
},
|
||||
value = textState,
|
||||
onValueChange = { textState = it },
|
||||
placeHolder = "Search ${title.value.lowercase()}"
|
||||
placeHolder = "Search ${title.value}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -13,47 +14,97 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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 com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.PaletteView
|
||||
import com.owenlejeune.tvtime.ui.components.TopLevelSwitch
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@Composable
|
||||
fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
val usePreferences = remember { mutableStateOf(preferences.usePreferences) }
|
||||
TopLevelSwitch(
|
||||
text = "Enable Preferences",
|
||||
checkedState = usePreferences,
|
||||
onCheckChanged = { isChecked ->
|
||||
usePreferences.value = isChecked
|
||||
preferences.usePreferences = isChecked
|
||||
}
|
||||
)
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
val shouldShowPalette = remember { mutableStateOf(false) }
|
||||
Text(
|
||||
text = "Show material palette",
|
||||
color = if (usePreferences.value) {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
} else {
|
||||
MaterialTheme.colorScheme.outline
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(12.dp)
|
||||
.clickable(
|
||||
enabled = usePreferences.value,
|
||||
onClick = {
|
||||
shouldShowPalette.value = true
|
||||
}
|
||||
Column(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
// 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
|
||||
)
|
||||
)
|
||||
if (shouldShowPalette.value) {
|
||||
PaletteDialog(shouldShowPalette)
|
||||
DebugOptions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DebugOptions() {
|
||||
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) {
|
||||
PaletteDialog(shouldShowPalette)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,18 +112,11 @@ fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
private fun PaletteDialog(showDialog: MutableState<Boolean>) {
|
||||
AlertDialog(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
title = {
|
||||
Text(text = "Palette")
|
||||
},
|
||||
text = {
|
||||
PaletteView()
|
||||
},
|
||||
title = { Text(text = "Palette") },
|
||||
text = { PaletteView() },
|
||||
dismissButton = {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = { showDialog.value = false }
|
||||
) {
|
||||
Text(text = "Dismiss", color = Color.White)
|
||||
TextButton(onClick = { showDialog.value = false }) {
|
||||
Text("Dismiss")
|
||||
}
|
||||
},
|
||||
confirmButton = {},
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">TVTime</string>
|
||||
|
||||
<!-- nav -->
|
||||
<string name="nav_movies_title">Films</string>
|
||||
<string name="nav_tv_title">Télé</string>
|
||||
<string name="nav_favourites_title">Favoris</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>
|
||||
|
||||
<!-- 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>
|
||||
@@ -1,14 +1,26 @@
|
||||
<resources>
|
||||
<string name="app_name">TVTime</string>
|
||||
|
||||
<!-- nav -->
|
||||
<string name="nav_movies_title">Movies</string>
|
||||
<string name="nav_tv_title">TV</string>
|
||||
<string name="nav_favourites_title">Favourites</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_popular_title">Popular</string>
|
||||
<string name="nav_top_rated_title">Top Rated</string>
|
||||
<string name="nav_upcoming_title">Upcoming</string>
|
||||
<string name="nav_tv_airing_today_title">Airing Today</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>
|
||||
Reference in New Issue
Block a user