This commit is contained in:
inhale-dir 2024-12-15 12:17:37 +01:00
parent 333b779c73
commit 8704b19277
7 changed files with 299 additions and 207 deletions

View File

@ -4,6 +4,14 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2024-12-14T13:53:37.083294865Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=37271FDJH00240" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>

View File

@ -89,4 +89,6 @@ dependencies {
implementation("androidx.compose.material:material-icons-extended:1.6.2")
implementation("androidx.compose.material3:material3:1.2.0")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.compose.foundation:foundation:1.6.2")
implementation("androidx.compose.animation:animation:1.6.2")
}

View File

@ -13,6 +13,7 @@ import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import android.util.Log
private const val THEME_MODE = "theme_mode"
private val Context.dataStore by preferencesDataStore(name = "settings")
@ -39,14 +40,14 @@ class SettingsDataStore(private val context: Context) {
val mode = preferences[PreferencesKeys.LOCATION_MODE_KEY] ?: "static"
when (mode) {
"static" -> Pair(
preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 52.520008,
preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 13.404954
preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 0.0,
preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 0.0
)
"gps" -> Pair(
preferences[PreferencesKeys.GPS_LAT_KEY] ?: preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 52.520008,
preferences[PreferencesKeys.GPS_LNG_KEY] ?: preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 13.404954
preferences[PreferencesKeys.GPS_LAT_KEY] ?: 0.0,
preferences[PreferencesKeys.GPS_LNG_KEY] ?: 0.0
)
else -> Pair(52.520008, 13.404954)
else -> Pair(0.0, 0.0)
}
}
@ -72,16 +73,25 @@ class SettingsDataStore(private val context: Context) {
}
suspend fun saveLocation(latitude: Double, longitude: Double, mode: String? = null) {
Log.d("GPS_DEBUG", """
Saving location:
Latitude: $latitude
Longitude: $longitude
Mode: $mode
""".trimIndent())
context.dataStore.edit { preferences ->
val currentMode = mode ?: preferences[PreferencesKeys.LOCATION_MODE_KEY] ?: "static"
when (currentMode) {
"static" -> {
preferences[PreferencesKeys.STATIC_LAT_KEY] = latitude
preferences[PreferencesKeys.STATIC_LNG_KEY] = longitude
Log.d("GPS_DEBUG", "Saved static location")
}
"gps" -> {
preferences[PreferencesKeys.GPS_LAT_KEY] = latitude
preferences[PreferencesKeys.GPS_LNG_KEY] = longitude
Log.d("GPS_DEBUG", "Saved GPS location")
}
}
}
@ -167,15 +177,15 @@ class SettingsDataStore(private val context: Context) {
"gps" -> {
getCurrentLocation() ?: context.dataStore.data.map { preferences ->
Pair(
preferences[PreferencesKeys.GPS_LAT_KEY] ?: preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 52.520008,
preferences[PreferencesKeys.GPS_LNG_KEY] ?: preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 13.404954
preferences[PreferencesKeys.GPS_LAT_KEY] ?: 0.0,
preferences[PreferencesKeys.GPS_LNG_KEY] ?: 0.0
)
}.first()
}
else -> context.dataStore.data.map { preferences ->
Pair(
preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 52.520008,
preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 13.404954
preferences[PreferencesKeys.STATIC_LAT_KEY] ?: 0.0,
preferences[PreferencesKeys.STATIC_LNG_KEY] ?: 0.0
)
}.first()
}
@ -191,4 +201,10 @@ class SettingsDataStore(private val context: Context) {
preferences[PreferencesKeys.THEME_MODE_KEY] = isDark
}
}
suspend fun saveFavoriteStations(stations: Set<String>) {
context.dataStore.edit { preferences ->
preferences[PreferencesKeys.FAVORITE_STATIONS] = stations.joinToString(",")
}
}
}

View File

@ -20,6 +20,10 @@ import com.example.tank.di.NetworkModule
import com.example.tank.ui.theme.TankTheme
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.core.tween
@Composable
fun MainScreen() {
@ -58,7 +62,7 @@ private fun MainContent() {
val navController = rememberNavController()
val context = LocalContext.current
val settingsDataStore = remember { SettingsDataStore(context) }
var isDarkTheme by remember { mutableStateOf(false) }
var isDarkTheme by remember { mutableStateOf(true) }
val scope = rememberCoroutineScope()
// Load saved theme preference
@ -70,15 +74,19 @@ private fun MainContent() {
TankTheme(darkTheme = isDarkTheme) {
Scaffold(
modifier = Modifier.animateContentSize(),
topBar = {
CenterAlignedTopAppBar(
title = { Text("Fuel Prices") },
actions = {
IconButton(onClick = {
navController.navigate("settings") {
launchSingleTop = true
}
}) {
IconButton(
onClick = {
navController.navigate("settings") {
launchSingleTop = true
}
},
modifier = Modifier.animateContentSize()
) {
Icon(Icons.Default.Settings, contentDescription = "Settings")
}
}
@ -88,10 +96,22 @@ private fun MainContent() {
NavHost(
navController = navController,
startDestination = "prices",
modifier = Modifier.padding(padding)
modifier = Modifier
.padding(padding)
.animateContentSize()
) {
composable("prices") { PricesScreen() }
composable("settings") {
composable(
"prices",
enterTransition = { fadeIn(animationSpec = tween(300)) },
exitTransition = { fadeOut(animationSpec = tween(300)) }
) {
PricesScreen()
}
composable(
"settings",
enterTransition = { fadeIn(animationSpec = tween(300)) },
exitTransition = { fadeOut(animationSpec = tween(300)) }
) {
SettingsScreen(
navController = navController,
isDarkTheme = isDarkTheme,
@ -102,7 +122,13 @@ private fun MainContent() {
}
)
}
composable("map") { MapScreen(navController = navController) }
composable(
"map",
enterTransition = { fadeIn(animationSpec = tween(300)) },
exitTransition = { fadeOut(animationSpec = tween(300)) }
) {
MapScreen(navController = navController)
}
}
}
}

View File

@ -3,6 +3,7 @@ package com.example.tank.ui.screens
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -43,8 +44,15 @@ import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationResult
import android.os.Looper
import com.google.android.gms.tasks.CancellationTokenSource
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.animation.animateContentSize
@OptIn(ExperimentalMaterialApi::class)
@OptIn(
ExperimentalMaterialApi::class,
ExperimentalFoundationApi::class
)
@Composable
fun PricesScreen(viewModel: StationsViewModel = viewModel()) {
val context = LocalContext.current
@ -76,10 +84,8 @@ fun PricesScreen(viewModel: StationsViewModel = viewModel()) {
}
val locationRequest = remember {
LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000)
.setWaitForAccurateLocation(true)
.setMinUpdateIntervalMillis(500)
.setMaxUpdateDelayMillis(1000)
LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
.setMinUpdateDistanceMeters(10f)
.build()
}
@ -87,12 +93,22 @@ fun PricesScreen(viewModel: StationsViewModel = viewModel()) {
object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
result.lastLocation?.let { location ->
Log.d("PricesScreen", "Location update received: ${location.latitude}, ${location.longitude}")
Log.d("GPS_DEBUG", """
Location Update Received:
Latitude: ${location.latitude}
Longitude: ${location.longitude}
Accuracy: ${location.accuracy}m
Speed: ${location.speed}m/s
Time: ${location.time}
Provider: ${location.provider}
Bearing: ${location.bearing}
Altitude: ${location.altitude}
""".trimIndent())
scope.launch {
settingsDataStore.saveLocation(location.latitude, location.longitude)
viewModel.loadStations(location.latitude, location.longitude, selectedRadius)
}
}
} ?: Log.e("GPS_DEBUG", "Location result was null")
}
}
}
@ -107,41 +123,50 @@ fun PricesScreen(viewModel: StationsViewModel = viewModel()) {
// Add location mode collection
LaunchedEffect(Unit) {
settingsDataStore.locationMode.collect { mode ->
Log.d("PricesScreen", "Location mode changed to: $mode")
Log.d("GPS_DEBUG", "Location mode changed to: $mode")
locationMode = mode
// Reload stations when location mode changes
when {
mode == "gps" &&
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED -> {
Log.d("PricesScreen", "GPS mode and permission granted")
Log.d("GPS_DEBUG", "GPS mode and permission granted")
try {
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
context.mainLooper
).addOnSuccessListener {
Log.d("PricesScreen", "Location updates requested successfully")
}.addOnFailureListener { exception ->
Log.e("PricesScreen", "Failed to request location updates", exception)
}
fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
.addOnSuccessListener { location ->
if (location != null) {
Log.d("GPS_DEBUG", """
Initial GPS Location:
Latitude: ${location.latitude}
Longitude: ${location.longitude}
Accuracy: ${location.accuracy}m
Provider: ${location.provider}
Is Mock Location: ${location.isFromMockProvider}
Elapsed Time: ${location.elapsedRealtimeNanos}
""".trimIndent())
scope.launch {
settingsDataStore.saveLocation(location.latitude, location.longitude)
viewModel.loadStations(location.latitude, location.longitude, selectedRadius)
}
} else {
Log.e("GPS_DEBUG", "Initial location request returned null")
}
}
.addOnFailureListener { e ->
Log.e("GPS_DEBUG", "Failed to get location: ${e.message}", e)
}
} catch (e: SecurityException) {
Log.e("PricesScreen", "Security exception when getting location", e)
// Fallback to saved location
scope.launch {
val savedLocation = settingsDataStore.selectedLocation.first()
viewModel.loadStations(savedLocation.first, savedLocation.second, selectedRadius)
}
Log.e("GPS_DEBUG", "Security exception when getting location", e)
}
}
mode == "gps" -> {
Log.e("GPS_DEBUG", """
GPS mode but no permission:
FINE_LOCATION permission: ${ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)}
COARSE_LOCATION permission: ${ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)}
""".trimIndent())
}
else -> {
Log.d("PricesScreen", "Using static mode or GPS permission denied")
// Use saved location for static mode or when GPS is not available
scope.launch {
val savedLocation = settingsDataStore.selectedLocation.first()
Log.d("PricesScreen", "Using saved location: ${savedLocation.first}, ${savedLocation.second}")
viewModel.loadStations(savedLocation.first, savedLocation.second, selectedRadius)
}
Log.d("GPS_DEBUG", "Using static mode")
}
}
}
@ -259,108 +284,102 @@ fun PricesScreen(viewModel: StationsViewModel = viewModel()) {
) {
when {
error != null -> {
Column(
Box(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
.pullRefresh(pullRefreshState)
) {
Text(
text = error ?: "An error occurred",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.error
)
Text(
text = "Pull down to refresh",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 8.dp)
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = error ?: "An error occurred",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.error
)
Text(
text = "Pull down to refresh",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 8.dp)
)
}
PullRefreshIndicator(
refreshing = isLoading,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter)
)
}
}
stations.isEmpty() && !isLoading -> {
Column(
Box(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
.pullRefresh(pullRefreshState)
) {
Text(
text = "No stations found",
style = MaterialTheme.typography.bodyLarge
)
Text(
text = "Pull down to refresh",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 8.dp)
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "No stations found",
style = MaterialTheme.typography.bodyLarge
)
Text(
text = "Pull down to refresh",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 8.dp)
)
}
PullRefreshIndicator(
refreshing = isLoading,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter)
)
}
}
else -> {
LazyColumn(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.pullRefresh(pullRefreshState),
state = rememberLazyListState(),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
// Favorites section
if (favoriteStations.isNotEmpty()) {
item {
Text(
text = "Favorites",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(bottom = 8.dp)
)
}
items(stations.filter { station ->
favoriteStations.contains(station.id)
}) { station ->
FavoriteStationCard(
station = station,
selectedFuelType = selectedFuelType,
onFavoriteClick = { stationId ->
scope.launch {
settingsDataStore.toggleFavorite(stationId)
}
}
)
}
item {
Divider(
modifier = Modifier.padding(vertical = 16.dp),
color = MaterialTheme.colorScheme.outlineVariant
)
Text(
text = "All Stations",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(bottom = 8.dp)
)
}
}
// Regular stations
items(stations.filter { station ->
!favoriteStations.contains(station.id) &&
when (selectedFuelType.lowercase()) {
"e5" -> station.e5 != null
"e10" -> station.e10 != null
"diesel" -> station.diesel != null
else -> true
}
}) { station ->
items(
items = stations,
key = { station -> station.id }
) { station ->
StationCard(
station = station,
selectedFuelType = selectedFuelType,
isFavorite = favoriteStations.contains(station.id),
onFavoriteClick = { stationId ->
scope.launch {
settingsDataStore.toggleFavorite(stationId)
if (favoriteStations.contains(stationId)) {
settingsDataStore.saveFavoriteStations(
favoriteStations.filter { it != stationId }.toSet()
)
} else {
settingsDataStore.saveFavoriteStations(
favoriteStations + stationId
)
}
}
}
},
modifier = Modifier
.animateContentSize()
)
}
}
@ -381,7 +400,8 @@ private fun StationCard(
station: Station,
selectedFuelType: String,
isFavorite: Boolean,
onFavoriteClick: (String) -> Unit
onFavoriteClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
Card(
modifier = Modifier

View File

@ -6,8 +6,11 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.LocationOn
import androidx.compose.material.icons.filled.MyLocation
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -20,13 +23,18 @@ import com.example.tank.di.NetworkModule
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import kotlinx.coroutines.launch
import androidx.compose.material.icons.Icons
import androidx.core.content.ContextCompat
import androidx.compose.foundation.background
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.draw.clip
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.rememberScrollState
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.tank.ui.viewmodel.StationsViewModel
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.ScrollableDefaults
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -38,6 +46,8 @@ fun SettingsScreen(
val context = LocalContext.current
val settingsDataStore = remember { SettingsDataStore(context) }
val scope = rememberCoroutineScope()
val viewModel: StationsViewModel = viewModel()
val scrollState = rememberScrollState()
var selectedFuelType by remember { mutableStateOf("") }
var selectedLocation by remember { mutableStateOf<Pair<Double, Double>?>(null) }
@ -45,15 +55,15 @@ fun SettingsScreen(
var apiKey by remember { mutableStateOf("") }
var locationMode by remember { mutableStateOf("static") }
val fuelTypes = listOf(
"DIESEL" to "Diesel",
"E5" to "Super E5",
"E10" to "Super E10"
)
val fuelTypes = remember {
listOf(
"DIESEL" to "Diesel",
"E5" to "Super E5",
"E10" to "Super E10"
)
}
val radiusOptions = listOf(5, 10, 15, 20)
// Add location services client
val radiusOptions = remember { listOf(5, 10, 15, 20) }
val fusedLocationClient = remember {
LocationServices.getFusedLocationProviderClient(context)
}
@ -148,7 +158,7 @@ fun SettingsScreen(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.verticalScroll(rememberScrollState())
.verticalScroll(scrollState)
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
@ -160,6 +170,55 @@ fun SettingsScreen(
modifier = Modifier.padding(bottom = 8.dp)
)
// Appearance Section (Moved up)
SettingsSection(title = "Appearance") {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
"Theme",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
FilterChip(
selected = !isDarkTheme,
onClick = { onThemeChanged(false) },
label = { Text("Light") },
leadingIcon = {
Icon(
Icons.Default.LightMode,
contentDescription = "Light Theme"
)
},
colors = FilterChipDefaults.filterChipColors(
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
)
FilterChip(
selected = isDarkTheme,
onClick = { onThemeChanged(true) },
label = { Text("Dark") },
leadingIcon = {
Icon(
Icons.Default.DarkMode,
contentDescription = "Dark Theme"
)
},
colors = FilterChipDefaults.filterChipColors(
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
)
}
}
}
// Location Section
SettingsSection(title = "Location") {
Column(
@ -243,59 +302,39 @@ fun SettingsScreen(
)
}
// Only show location card for static mode
// Show map button for static mode
if (locationMode == "static") {
Button(
onClick = {
navController.navigate("map")
},
modifier = Modifier.fillMaxWidth()
) {
Text("Select Location on Map")
}
}
// Current Location Display
if (selectedLocation != null) {
Card(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
.padding(vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
Column(
modifier = Modifier.padding(16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
imageVector = if (locationMode == "static")
Icons.Default.LocationOn
else Icons.Default.MyLocation,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(20.dp)
)
Text(
text = if (selectedLocation != null) {
String.format(
"%.4f, %.4f",
selectedLocation!!.first,
selectedLocation!!.second
)
} else {
"No location selected"
},
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
TextButton(
onClick = { navController.navigate("map") },
contentPadding = PaddingValues(horizontal = 8.dp)
) {
Text(
"Map",
style = MaterialTheme.typography.bodyMedium
)
}
Text(
text = "Latitude: ${String.format("%.6f", selectedLocation?.first)}",
style = MaterialTheme.typography.bodyMedium
)
Text(
text = "Longitude: ${String.format("%.6f", selectedLocation?.second)}",
style = MaterialTheme.typography.bodyMedium
)
}
}
}
@ -359,7 +398,8 @@ fun SettingsScreen(
},
label = { Text("${radius}km") },
colors = FilterChipDefaults.filterChipColors(
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
)
}
@ -384,26 +424,6 @@ fun SettingsScreen(
)
}
// Add Theme Section
SettingsSection(title = "Appearance") {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Dark Theme",
style = MaterialTheme.typography.bodyLarge
)
Switch(
checked = isDarkTheme,
onCheckedChange = { onThemeChanged(it) }
)
}
}
Spacer(modifier = Modifier.height(16.dp))
// Save Button
@ -445,7 +465,7 @@ private fun SettingsSection(
Column(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.clip(remember { RoundedCornerShape(12.dp) })
.background(MaterialTheme.colorScheme.surface)
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)

View File

@ -35,7 +35,7 @@ private val LightColorScheme = lightColorScheme(
@Composable
fun TankTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
darkTheme: Boolean = true,
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit