mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Added even more tweaks to Dialog Layouts and UI
This commit is contained in:
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-54
@@ -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)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user