Added even more tweaks to Dialog Layouts and UI

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:47 +00:00
1 parent 5842239e26
commit e3955239f3
6 files changed
+219 -260

No files matched your search

@@ -9,7 +9,9 @@ import androidx.compose.material3.Typography
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
@@ -19,19 +21,41 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
val LocalSpacing = compositionLocalOf { Spacing }
//val MaterialTheme.spacing: Spacing
// @Composable @ReadOnlyComposable get() = Spacing
data object SpacingDefaults {
internal const val EXTRA_SMALL = 4
internal const val SMALL = 6
internal const val MEDIUM = 8
internal const val LARGE = 12
internal const val EXTRA_LARGE = 16
}
data object Spacing {
val extraSmall = SpacingDefaults.EXTRA_SMALL.dp
val small = SpacingDefaults.SMALL.dp
val medium = SpacingDefaults.MEDIUM.dp
val large = SpacingDefaults.LARGE.dp
val extraLarge = SpacingDefaults.EXTRA_LARGE.dp
}
@Composable @Composable
fun MainTheme(isDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { fun MainTheme(isDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val view = LocalView.current val view = LocalView.current
if (view.isInEditMode) { if (view.isInEditMode) {
MaterialTheme(darkScheme, shapes, typography, content) MaterialTheme(darkScheme, shapes, typography, content)
} else { } else {
val colorScheme = if (isDarkTheme) darkScheme else lightScheme CompositionLocalProvider(LocalSpacing provides Spacing) {
SideEffect { val colorScheme = if (isDarkTheme) darkScheme else lightScheme
val window = (view.context as ComponentActivity).window SideEffect {
val insetsController = WindowCompat.getInsetsController(window, view) val window = (view.context as ComponentActivity).window
insetsController.isAppearanceLightStatusBars = false val insetsController = WindowCompat.getInsetsController(window, view)
insetsController.isAppearanceLightStatusBars = false
}
MaterialTheme(colorScheme, shapes, typography, content)
} }
MaterialTheme(colorScheme, shapes, typography, content)
} }
} }
@@ -38,10 +38,12 @@ 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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.predict.NearEarthObject import com.rtbishop.look4sat.domain.predict.NearEarthObject
import com.rtbishop.look4sat.domain.predict.OrbitalData import com.rtbishop.look4sat.domain.predict.OrbitalData
import com.rtbishop.look4sat.domain.predict.OrbitalPass import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.presentation.LocalSpacing
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@@ -253,6 +255,34 @@ fun getDefaultPass(): OrbitalPass {
return OrbitalPass(0L, 0.0, 0L, 0.0, 0, 0.0, satellite, 0f) return OrbitalPass(0L, 0.0, 0L, 0.0, 0, 0.0, satellite, 0f)
} }
@Composable
fun SharedDialog(
title: String, onCancel: () -> Unit, onAccept: () -> Unit, content: @Composable () -> Unit
) {
val padding = LocalSpacing.current.extraLarge
Dialog(onDismissRequest = { onCancel() }) {
ElevatedCard {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(padding)
) {
Text(
text = title,
fontSize = 18.sp,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(start = padding, top = padding, end = padding)
)
content()
Row(modifier = Modifier.padding(start = padding, bottom = padding, end = padding)) {
CardButton(onClick = onCancel, text = stringResource(id = R.string.btn_cancel))
Spacer(modifier = Modifier.weight(1f))
CardButton(onClick = onAccept, text = stringResource(id = R.string.btn_accept))
}
}
}
}
}
//fun Modifier.onClick(onClick: () -> Unit): Modifier = composed { //fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
// clickable(remember { MutableInteractionSource() }, null) { onClick() } // clickable(remember { MutableInteractionSource() }, null) { onClick() }
//} //}
@@ -22,16 +22,13 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -39,22 +36,22 @@ import androidx.compose.material3.Slider
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableDoubleStateOf
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.LocalSpacing
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton import com.rtbishop.look4sat.presentation.components.SharedDialog
private val allModes = listOf( private val allModes = listOf(
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3", "AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
@@ -64,86 +61,75 @@ private val allModes = listOf(
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT" "PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
) )
@Preview(showBackground = true) @Preview
@Composable @Composable
private fun PassesDialogPreview() { private fun PassesDialogPreview() {
MainTheme { PassesDialog(24, 16.0, {}) { _, _ -> } } MainTheme { PassesDialog(24, 16.0, {}) { _, _ -> } }
} }
@Composable @Composable
fun PassesDialog(hours: Int, elev: Double, dismiss: () -> Unit, save: (Int, Double) -> Unit) { fun PassesDialog(hours: Int, elevation: Double, cancel: () -> Unit, accept: (Int, Double) -> Unit) {
val maxWidthModifier = Modifier.fillMaxWidth()
val hoursValue = remember { mutableIntStateOf(hours) } val hoursValue = remember { mutableIntStateOf(hours) }
val elevationValue = remember { mutableIntStateOf(elev.toInt()) } val elevationValueNew = remember { mutableDoubleStateOf(elevation) }
Dialog(onDismissRequest = { dismiss() }) { val onAccept = {
ElevatedCard { accept(hoursValue.intValue, elevationValueNew.doubleValue).also { cancel() }
Column( }
horizontalAlignment = Alignment.CenterHorizontally, SharedDialog(title = "Passes", onCancel = cancel, onAccept = onAccept) {
verticalArrangement = Arrangement.spacedBy(6.dp), SliderRow(
modifier = maxWidthModifier.padding(16.dp) title = "Show passes above",
) { value = elevationValueNew.doubleValue,
Text(text = "Passes", fontSize = 18.sp, color = MaterialTheme.colorScheme.primary) valuePostfix = "°",
Spacer(modifier = Modifier.height(8.dp)) valueResId = R.drawable.ic_elevation,
Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.Bottom) { valueRange = 0f..60f
Text(text = "Show passes above", fontSize = 16.sp, modifier = Modifier.weight(1f)) ) { elevationValueNew.doubleValue = it.toDouble() }
Icon( SliderRow(
painter = painterResource(id = R.drawable.ic_elevation), title = "Show passes within",
contentDescription = null, value = hoursValue.intValue.toDouble(),
tint = MaterialTheme.colorScheme.primary, valuePostfix = "h",
modifier = Modifier valueResId = R.drawable.ic_time,
.size(20.dp) valueRange = 1f..240f
.padding(bottom = 4.dp) ) { hoursValue.intValue = it.toInt() }
) }
Text( }
text = "${elevationValue.intValue}°",
fontSize = 18.sp, @Composable
fontWeight = FontWeight.Medium, private fun SliderRow(
color = MaterialTheme.colorScheme.primary title: String,
) value: Double,
} valuePostfix: String,
Slider( valueResId: Int,
value = elevationValue.intValue.toFloat(), valueRange: ClosedFloatingPointRange<Float>,
onValueChange = { elevationValue.intValue = it.toInt() }, onChange: (Float) -> Unit
valueRange = 0f..60f ) {
) Column(
Spacer(modifier = Modifier.height(8.dp)) horizontalAlignment = Alignment.CenterHorizontally,
Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.Bottom) { verticalArrangement = Arrangement.spacedBy(LocalSpacing.current.medium),
Text(text = "Show passes within", fontSize = 16.sp, modifier = Modifier.weight(1f)) modifier = Modifier.padding(horizontal = LocalSpacing.current.extraLarge)
Icon( ) {
painter = painterResource(id = R.drawable.ic_time), Row(
contentDescription = null, horizontalArrangement = Arrangement.spacedBy(LocalSpacing.current.medium),
tint = MaterialTheme.colorScheme.primary, verticalAlignment = Alignment.CenterVertically
modifier = Modifier ) {
.size(20.dp) Text(
.padding(bottom = 4.dp) text = title,
) fontSize = 16.sp,
Text( modifier = Modifier.weight(1f),
text = "${hoursValue.intValue}h", color = MaterialTheme.colorScheme.onSurface
fontSize = 18.sp, )
fontWeight = FontWeight.Medium, Icon(
color = MaterialTheme.colorScheme.primary painter = painterResource(id = valueResId),
) contentDescription = null,
} tint = MaterialTheme.colorScheme.primary,
Slider( modifier = Modifier.size(20.dp)
value = hoursValue.intValue.toFloat(), )
onValueChange = { hoursValue.intValue = it.toInt() }, Text(
valueRange = 1f..240f text = "${value.toInt()}$valuePostfix",
) fontSize = 18.sp,
Row( fontWeight = FontWeight.Medium,
horizontalArrangement = Arrangement.SpaceBetween, color = MaterialTheme.colorScheme.primary
verticalAlignment = Alignment.CenterVertically, )
modifier = maxWidthModifier
) {
CardButton(onClick = { dismiss() }, text = stringResource(id = R.string.btn_cancel))
CardButton(
onClick = {
save(hoursValue.intValue, elevationValue.intValue.toDouble())
dismiss()
}, text = stringResource(id = R.string.btn_accept)
)
}
}
} }
Slider(value = value.toFloat(), onValueChange = onChange, valueRange = valueRange)
} }
} }
@@ -154,69 +140,52 @@ private fun RadiosDialogPreview() {
} }
@Composable @Composable
fun RadiosDialog(modes: List<String>, dismiss: () -> Unit, save: (List<String>) -> Unit) { fun RadiosDialog(modes: List<String>, cancel: () -> Unit, accept: (List<String>) -> Unit) {
val maxWidthModifier = Modifier.fillMaxWidth(1f)
val selected = remember { mutableStateListOf<String>().apply { addAll(modes) } } val selected = remember { mutableStateListOf<String>().apply { addAll(modes) } }
val select = { mode: String -> if (selected.contains(mode)) selected.remove(mode) else selected.add(mode) } val select = { mode: String ->
Dialog(onDismissRequest = { dismiss() }) { if (selected.contains(mode)) selected.remove(mode) else selected.add(mode)
ElevatedCard { }
Column( val onAccept = { accept(selected.toList()).also { cancel() } }
horizontalAlignment = Alignment.CenterHorizontally, SharedDialog(title = "Radios", onCancel = cancel, onAccept = onAccept) {
verticalArrangement = Arrangement.spacedBy(16.dp), LazyVerticalGrid(
modifier = maxWidthModifier.padding(vertical = 16.dp) columns = GridCells.Fixed(1),
) { modifier = Modifier
Text(text = "Radios", fontSize = 18.sp, color = MaterialTheme.colorScheme.primary) .fillMaxHeight(0.69f)
LazyVerticalGrid( .background(MaterialTheme.colorScheme.background),
columns = GridCells.Fixed(1), horizontalArrangement = Arrangement.spacedBy(1.dp),
modifier = Modifier verticalArrangement = Arrangement.spacedBy(1.dp)
.background(MaterialTheme.colorScheme.background) ) {
.weight(1f), item { HorizontalDivider(color = MaterialTheme.colorScheme.surface) }
horizontalArrangement = Arrangement.spacedBy(1.dp), itemsIndexed(allModes) { index, item ->
verticalArrangement = Arrangement.spacedBy(1.dp) Surface {
) { Row(
item { HorizontalDivider(thickness = 0.dp, color = MaterialTheme.colorScheme.surface) } verticalAlignment = Alignment.CenterVertically,
itemsIndexed(allModes) { index, item -> modifier = Modifier
Surface { .background(MaterialTheme.colorScheme.surface)
Row(verticalAlignment = Alignment.CenterVertically, .clickable { select(item) }
modifier = Modifier ) {
.background(MaterialTheme.colorScheme.surface) Text(
.clickable { select(item) }) { text = "${index + 1}).",
Text( modifier = Modifier.padding(start = 16.dp, end = 8.dp),
text = "$index).", fontWeight = FontWeight.Normal,
modifier = Modifier.padding(start = 8.dp, end = 6.dp), color = MaterialTheme.colorScheme.primary
fontWeight = FontWeight.Normal, )
color = MaterialTheme.colorScheme.primary Text(
) text = item,
Text( modifier = Modifier.weight(1f),
text = item, fontWeight = FontWeight.Medium,
modifier = Modifier.weight(1f), maxLines = 1,
fontWeight = FontWeight.Medium, overflow = TextOverflow.Ellipsis
maxLines = 1, )
overflow = TextOverflow.Ellipsis Checkbox(
) checked = selected.contains(item),
Checkbox( onCheckedChange = null,
checked = selected.contains(item), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
onCheckedChange = null, )
modifier = Modifier.padding(8.dp)
)
}
}
} }
item { HorizontalDivider(thickness = 24.dp, color = MaterialTheme.colorScheme.surface) }
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = maxWidthModifier.padding(horizontal = 16.dp)
) {
CardButton(onClick = { dismiss() }, text = stringResource(id = R.string.btn_cancel))
CardButton(
onClick = {
save(selected.toList())
dismiss()
}, text = stringResource(id = R.string.btn_accept)
)
} }
} }
item { HorizontalDivider(color = MaterialTheme.colorScheme.surface) }
} }
} }
} }
@@ -71,12 +71,12 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U
val showPassesDialog = { uiState.takeAction(PassesAction.TogglePassesDialog) } val showPassesDialog = { uiState.takeAction(PassesAction.TogglePassesDialog) }
val showRadiosDialog = { uiState.takeAction(PassesAction.ToggleRadiosDialog) } val showRadiosDialog = { uiState.takeAction(PassesAction.ToggleRadiosDialog) }
if (uiState.isPassesDialogShown) { if (uiState.isPassesDialogShown) {
PassesDialog(hours = uiState.hours, elev = uiState.elevation, dismiss = showPassesDialog) { hours, elevation -> PassesDialog(hours = uiState.hours, elevation = uiState.elevation, cancel = showPassesDialog) { hours, elevation ->
uiState.takeAction(PassesAction.FilterPasses(hours, elevation)) uiState.takeAction(PassesAction.FilterPasses(hours, elevation))
} }
} }
if (uiState.isRadiosDialogShown) { if (uiState.isRadiosDialogShown) {
RadiosDialog(modes = uiState.modes, dismiss = showRadiosDialog) { modes -> RadiosDialog(modes = uiState.modes, cancel = showRadiosDialog) { modes ->
uiState.takeAction(PassesAction.FilterRadios(modes)) uiState.takeAction(PassesAction.FilterRadios(modes))
} }
} }
@@ -3,29 +3,25 @@ package com.rtbishop.look4sat.presentation.satellites
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
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.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.components.SharedDialog
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
@@ -38,55 +34,42 @@ private fun TypeDialogPreview() {
fun TypesDialog( fun TypesDialog(
items: List<String>, selected: String, dismiss: () -> Unit, select: (String) -> Unit items: List<String>, selected: String, dismiss: () -> Unit, select: (String) -> Unit
) { ) {
val height = LocalConfiguration.current.screenHeightDp SharedDialog(title = "Select category", onCancel = dismiss, onAccept = {}) {
Dialog(onDismissRequest = { dismiss() }) { LazyVerticalGrid(
ElevatedCard { columns = GridCells.Adaptive(240.dp),
Column( modifier = Modifier
horizontalAlignment = Alignment.CenterHorizontally, .fillMaxHeight(0.69f)
modifier = Modifier.heightIn(max = height.times(0.80).dp) .background(MaterialTheme.colorScheme.background),
) { horizontalArrangement = Arrangement.spacedBy(1.dp),
Text( verticalArrangement = Arrangement.spacedBy(1.dp)
text = "Select category", ) {
fontSize = 18.sp, item { HorizontalDivider(color = MaterialTheme.colorScheme.surface) }
textAlign = TextAlign.Center, itemsIndexed(items) { index, item ->
color = MaterialTheme.colorScheme.primary, Row(verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(top = 8.dp, bottom = 4.dp) modifier = Modifier
) .background(MaterialTheme.colorScheme.surface)
LazyVerticalGrid( .clickable { select(item) }) {
columns = GridCells.Adaptive(240.dp), Text(
modifier = Modifier.background(MaterialTheme.colorScheme.background), text = "${index + 1}).",
horizontalArrangement = Arrangement.spacedBy(1.dp), modifier = Modifier.padding(start = 16.dp, end = 8.dp),
verticalArrangement = Arrangement.spacedBy(1.dp) fontWeight = FontWeight.Normal,
) { color = MaterialTheme.colorScheme.primary
itemsIndexed(items) { index, item -> )
Row(verticalAlignment = Alignment.CenterVertically, Text(
modifier = Modifier text = item,
.background(MaterialTheme.colorScheme.surface) modifier = Modifier.weight(1f),
.clickable { select(item) }) { fontWeight = FontWeight.Medium,
Text( maxLines = 1,
text = "$index).", overflow = TextOverflow.Ellipsis
modifier = Modifier.padding(start = 12.dp, end = 6.dp), )
fontWeight = FontWeight.Normal, RadioButton(
color = MaterialTheme.colorScheme.primary selected = item == selected,
) onClick = null,
Text( modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
text = item, )
modifier = Modifier.weight(1f),
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
RadioButton(
selected = item == selected,
onClick = null,
modifier = Modifier.padding(
start = 8.dp, top = 8.dp, end = 12.dp, bottom = 8.dp
)
)
}
}
} }
} }
item { HorizontalDivider(color = MaterialTheme.colorScheme.surface) }
} }
} }
} }
@@ -1,26 +1,15 @@
package com.rtbishop.look4sat.presentation.settings package com.rtbishop.look4sat.presentation.settings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton import com.rtbishop.look4sat.presentation.components.SharedDialog
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
@@ -32,40 +21,22 @@ private fun PositionDialogPreview() {
fun PositionDialog(lat: Double, lon: Double, dismiss: () -> Unit, save: (Double, Double) -> Unit) { fun PositionDialog(lat: Double, lon: Double, dismiss: () -> Unit, save: (Double, Double) -> Unit) {
val latValue = rememberSaveable { mutableStateOf(lat.toString()) } val latValue = rememberSaveable { mutableStateOf(lat.toString()) }
val lonValue = rememberSaveable { mutableStateOf(lon.toString()) } val lonValue = rememberSaveable { mutableStateOf(lon.toString()) }
val maxWidthModifier = Modifier.fillMaxWidth(1f) val titleText = stringResource(id = R.string.position_title)
Dialog(onDismissRequest = { dismiss() }) { val onAccept = { saveValues(latValue.value, lonValue.value, save).also { dismiss() } }
ElevatedCard { SharedDialog(title = titleText, onCancel = dismiss, onAccept = onAccept) {
Column( Text(text = stringResource(id = R.string.position_lat_text))
horizontalAlignment = Alignment.CenterHorizontally, OutlinedTextField(value = latValue.value, onValueChange = { latValue.value = it })
verticalArrangement = Arrangement.spacedBy(12.dp), Text(text = stringResource(id = R.string.position_lon_text))
modifier = maxWidthModifier.padding(12.dp) OutlinedTextField(value = lonValue.value, onValueChange = { lonValue.value = it })
) {
Text(
text = stringResource(id = R.string.position_title), color = MaterialTheme.colorScheme.primary
)
Text(text = stringResource(id = R.string.position_lat_text))
OutlinedTextField(value = latValue.value, onValueChange = { latValue.value = it })
Text(text = stringResource(id = R.string.position_lon_text))
OutlinedTextField(value = lonValue.value, onValueChange = { lonValue.value = it })
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
CardButton(onClick = { dismiss() }, text = stringResource(id = R.string.btn_cancel))
CardButton(
onClick = { saveValues(latValue.value, lonValue.value, dismiss, save) },
text = stringResource(id = R.string.btn_accept)
)
}
}
}
} }
} }
private fun saveValues(latValue: String, lonValue: String, dismiss: () -> Unit, save: (Double, Double) -> Unit) { private fun saveValues(latValue: String, lonValue: String, save: (Double, Double) -> Unit) {
val latitude = latValue.toDoubleOrNull() ?: 0.0 val latitude = latValue.toDoubleOrNull() ?: 0.0
val longitude = lonValue.toDoubleOrNull() ?: 0.0 val longitude = lonValue.toDoubleOrNull() ?: 0.0
val newLatitude = if (latitude > 90) 90.0 else if (latitude < -90) -90.0 else latitude val newLatitude = if (latitude > 90) 90.0 else if (latitude < -90) -90.0 else latitude
val newLongitude = if (longitude > 180) 180.0 else if (longitude < -180) -180.0 else longitude val newLongitude = if (longitude > 180) 180.0 else if (longitude < -180) -180.0 else longitude
save(newLatitude, newLongitude) save(newLatitude, newLongitude)
dismiss()
} }
@Preview(showBackground = true) @Preview(showBackground = true)
@@ -77,27 +48,9 @@ private fun LocatorDialogPreview() {
@Composable @Composable
fun LocatorDialog(qthLocator: String, dismiss: () -> Unit, save: (String) -> Unit) { fun LocatorDialog(qthLocator: String, dismiss: () -> Unit, save: (String) -> Unit) {
val locator = rememberSaveable { mutableStateOf(qthLocator) } val locator = rememberSaveable { mutableStateOf(qthLocator) }
val maxWidthModifier = Modifier.fillMaxWidth(1f) val onAccept = { save(locator.value).also { dismiss() } }
Dialog(onDismissRequest = { dismiss() }) { SharedDialog(title = "Radios", onCancel = dismiss, onAccept = onAccept) {
ElevatedCard { Text(text = stringResource(id = R.string.locator_text))
Column( OutlinedTextField(value = locator.value, onValueChange = { locator.value = it })
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(12.dp),
modifier = maxWidthModifier.padding(12.dp)
) {
Text(text = stringResource(id = R.string.locator_title), color = MaterialTheme.colorScheme.primary)
Text(text = stringResource(id = R.string.locator_text))
OutlinedTextField(value = locator.value, onValueChange = { locator.value = it })
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
CardButton(onClick = { dismiss() }, text = stringResource(id = R.string.btn_cancel))
CardButton(
onClick = {
save(locator.value)
dismiss()
}, text = stringResource(id = R.string.btn_accept)
)
}
}
}
} }
} }