mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
feat(settings): add TvSettingsScreen and integrate settings management
This commit is contained in:
@@ -13,6 +13,7 @@ import hu.bbara.purefin.navigation.tvLibrarySection
|
||||
import hu.bbara.purefin.navigation.tvLoginSection
|
||||
import hu.bbara.purefin.navigation.tvMovieSection
|
||||
import hu.bbara.purefin.navigation.tvPlayerSection
|
||||
import hu.bbara.purefin.navigation.tvSettingsSection
|
||||
import hu.bbara.purefin.navigation.tvSeriesSection
|
||||
|
||||
@Module
|
||||
@@ -60,4 +61,10 @@ object TvNavigationModule {
|
||||
fun provideTvLibraryEntryBuilder(): EntryProviderScope<Route>.() -> Unit = {
|
||||
tvLibrarySection()
|
||||
}
|
||||
|
||||
@IntoSet
|
||||
@Provides
|
||||
fun provideTvSettingsEntryBuilder(): EntryProviderScope<Route>.() -> Unit = {
|
||||
tvSettingsSection()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import hu.bbara.purefin.ui.screen.login.LoginScreen
|
||||
import hu.bbara.purefin.ui.screen.TvAppScreen
|
||||
import hu.bbara.purefin.ui.screen.library.TvLibraryScreen
|
||||
import hu.bbara.purefin.ui.screen.player.TvPlayerScreen
|
||||
import hu.bbara.purefin.ui.screen.settings.TvSettingsScreen
|
||||
|
||||
fun EntryProviderScope<Route>.tvHomeSection() {
|
||||
entry<Route.Home> {
|
||||
@@ -62,3 +63,9 @@ fun EntryProviderScope<Route>.tvLibrarySection() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun EntryProviderScope<Route>.tvSettingsSection() {
|
||||
entry<Route.SettingsRoute> {
|
||||
TvSettingsScreen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Home
|
||||
import androidx.compose.material.icons.outlined.Movie
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.Tv
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -27,6 +28,7 @@ import hu.bbara.purefin.ui.screen.home.TvHomeScreen
|
||||
import hu.bbara.purefin.ui.screen.home.components.TvDrawerDestinationItem
|
||||
import hu.bbara.purefin.ui.screen.home.components.TvNavigationDrawer
|
||||
import hu.bbara.purefin.ui.screen.library.TvLibraryScreen
|
||||
import hu.bbara.purefin.ui.screen.settings.TvSettingsScreen
|
||||
|
||||
@Composable
|
||||
fun TvAppScreen(
|
||||
@@ -62,7 +64,11 @@ fun TvAppScreen(
|
||||
LibraryKind.SERIES -> Icons.Outlined.Tv
|
||||
}
|
||||
)
|
||||
}
|
||||
} + TvDrawerDestinationItem(
|
||||
destination = Route.SettingsRoute,
|
||||
label = "Settings",
|
||||
icon = Icons.Outlined.Settings
|
||||
)
|
||||
}
|
||||
|
||||
LifecycleResumeEffect(Unit) {
|
||||
@@ -88,6 +94,12 @@ fun TvAppScreen(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
entry<Route.SettingsRoute> {
|
||||
TvSettingsScreen(
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TvNavigationDrawer(
|
||||
@@ -97,7 +109,7 @@ fun TvAppScreen(
|
||||
if (selectedDestination != destination) {
|
||||
backStack.clear()
|
||||
backStack.add(Route.Home)
|
||||
if (destination is Route.LibraryRoute) {
|
||||
if (destination != Route.Home) {
|
||||
backStack.add(destination)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
package hu.bbara.purefin.ui.screen.settings
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import hu.bbara.purefin.feature.settings.SettingsViewModel
|
||||
import hu.bbara.purefin.settings.SettingsOptions
|
||||
import java.util.Locale
|
||||
|
||||
@Composable
|
||||
fun TvSettingsScreen(
|
||||
viewModel: SettingsViewModel = hiltViewModel(),
|
||||
onBack: () -> Unit = viewModel::onBack,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
containerColor = MaterialTheme.colorScheme.background,
|
||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||
topBar = {
|
||||
TvSettingsTopBar(onBack = onBack)
|
||||
}
|
||||
) { innerPadding ->
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)
|
||||
) {
|
||||
item {
|
||||
Text(
|
||||
text = "Settings",
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier.padding(horizontal = 28.dp, vertical = 16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Text(
|
||||
text = "Playback",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(horizontal = 28.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
SettingsOptions.numberSettings.forEach { option ->
|
||||
item(key = option.key) {
|
||||
val value by viewModel.value(option).collectAsState(initial = option.defaultValue)
|
||||
TvNumberSettingItem(
|
||||
title = option.title,
|
||||
value = value,
|
||||
valueRange = option.valueRange,
|
||||
onValueChange = { viewModel.set(option, it) }
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
|
||||
SettingsOptions.booleanSettings.forEach { option ->
|
||||
item(key = option.key) {
|
||||
val value by viewModel.value(option).collectAsState(initial = option.defaultValue)
|
||||
TvBooleanSettingItem(
|
||||
title = option.title,
|
||||
value = value,
|
||||
onValueChange = { viewModel.set(option, it) }
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
|
||||
SettingsOptions.stringSettings.forEach { option ->
|
||||
item(key = option.key) {
|
||||
val value by viewModel.value(option).collectAsState(initial = option.defaultValue)
|
||||
TvStringSettingItem(
|
||||
title = option.title,
|
||||
value = value,
|
||||
onValueChange = { viewModel.set(option, it) }
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TvSettingsTopBar(
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
IconButton(onClick = onBack) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TvNumberSettingItem(
|
||||
title: String,
|
||||
value: Double,
|
||||
valueRange: ClosedFloatingPointRange<Double>,
|
||||
onValueChange: (Double) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
var sliderValue by remember(value) { mutableStateOf(value.toFloat()) }
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 28.dp, vertical = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
Text(
|
||||
text = String.format(Locale.US, "%.1f", sliderValue),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Slider(
|
||||
value = sliderValue,
|
||||
onValueChange = { sliderValue = it },
|
||||
onValueChangeFinished = { onValueChange(sliderValue.toDouble()) },
|
||||
valueRange = valueRange.start.toFloat()..valueRange.endInclusive.toFloat(),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TvBooleanSettingItem(
|
||||
title: String,
|
||||
value: Boolean,
|
||||
onValueChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onValueChange(!value) }
|
||||
.padding(horizontal = 28.dp, vertical = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
Switch(
|
||||
checked = value,
|
||||
onCheckedChange = onValueChange
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TvStringSettingItem(
|
||||
title: String,
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
label = { Text(title) },
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
capitalization = KeyboardCapitalization.Words
|
||||
),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 28.dp, vertical = 16.dp)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user