mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-04 11:37:22 +00:00
Restructured SettingsScreen layout, tweaked components
This commit is contained in:
1 parent
bfbe437ab1
commit
a68e466040
16 files changed
+236
-214
No files matched your search
@@ -17,7 +17,6 @@ import com.rtbishop.look4sat.data.repository.SettingsRepo
|
||||
import com.rtbishop.look4sat.data.source.LocalSource
|
||||
import com.rtbishop.look4sat.data.source.RemoteSource
|
||||
import com.rtbishop.look4sat.data.usecase.AddToCalendar
|
||||
import com.rtbishop.look4sat.data.usecase.OpenWebUrl
|
||||
import com.rtbishop.look4sat.data.usecase.ShowToast
|
||||
import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
||||
@@ -27,7 +26,6 @@ import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||
import com.rtbishop.look4sat.domain.source.ILocalSource
|
||||
import com.rtbishop.look4sat.domain.source.IRemoteSource
|
||||
import com.rtbishop.look4sat.domain.usecase.IAddToCalendar
|
||||
import com.rtbishop.look4sat.domain.usecase.IOpenWebUrl
|
||||
import com.rtbishop.look4sat.domain.usecase.IShowToast
|
||||
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
@@ -58,10 +56,6 @@ class MainContainer(private val context: Context) {
|
||||
return AddToCalendar(context)
|
||||
}
|
||||
|
||||
fun provideOpenWebUrl(): IOpenWebUrl {
|
||||
return OpenWebUrl(context)
|
||||
}
|
||||
|
||||
fun provideShowToast(): IShowToast {
|
||||
return ShowToast(context)
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ private val darkScheme = darkColorScheme(
|
||||
|
||||
private val shapes = Shapes(
|
||||
extraSmall = RoundedCornerShape(4.dp), // menus, snackbars, text fields
|
||||
small = RoundedCornerShape(6.dp), // buttons, chips
|
||||
medium = RoundedCornerShape(8.dp), // cards, small FABs
|
||||
small = RoundedCornerShape(8.dp), // buttons, chips
|
||||
medium = RoundedCornerShape(12.dp), // cards, small FABs
|
||||
large = RoundedCornerShape(24.dp), // extended FABs, FABs, nav drawers
|
||||
extraLarge = RoundedCornerShape(32.dp) // large FABs
|
||||
)
|
||||
|
||||
@@ -16,8 +16,8 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ElevatedButton
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
@@ -207,6 +207,19 @@ fun IconCard(action: () -> Unit, resId: Int, modifier: Modifier = Modifier) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PrimaryIconCard(modifier: Modifier = Modifier, resId: Int, onClick: () -> Unit) {
|
||||
val clickableMod = modifier.clickable { onClick() }
|
||||
ElevatedCard(
|
||||
modifier = Modifier.size(102.dp, 48.dp),
|
||||
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.primary)
|
||||
) {
|
||||
Box(modifier = clickableMod.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Icon(painter = painterResource(id = resId), contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CardLoadingIndicator() {
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
||||
@@ -320,7 +333,6 @@ fun ScreenColumn(
|
||||
floatingBar: @Composable () -> Unit = {},
|
||||
content: @Composable (Boolean) -> Unit = {}
|
||||
) {
|
||||
val surfaceCorners = LocalSpacing.current.large
|
||||
val isVerticalLayout = isVerticalLayout()
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
Box(modifier = Modifier.layoutPadding(), contentAlignment = Alignment.BottomCenter) {
|
||||
@@ -328,7 +340,6 @@ fun ScreenColumn(
|
||||
topBar(isVerticalLayout)
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
shape = RoundedCornerShape(topStart = surfaceCorners, topEnd = surfaceCorners),
|
||||
color = MaterialTheme.colorScheme.surfaceContainer
|
||||
) { content(isVerticalLayout) }
|
||||
}
|
||||
|
||||
+8
-19
@@ -3,19 +3,16 @@ package com.rtbishop.look4sat.presentation.satellites
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -49,6 +46,7 @@ import com.rtbishop.look4sat.presentation.common.CardLoadingIndicator
|
||||
import com.rtbishop.look4sat.presentation.common.EmptyListCard
|
||||
import com.rtbishop.look4sat.presentation.common.IconCard
|
||||
import com.rtbishop.look4sat.presentation.common.InfoDialog
|
||||
import com.rtbishop.look4sat.presentation.common.PrimaryIconCard
|
||||
import com.rtbishop.look4sat.presentation.common.TopBar
|
||||
import com.rtbishop.look4sat.presentation.common.infiniteMarquee
|
||||
import com.rtbishop.look4sat.presentation.common.isVerticalLayout
|
||||
@@ -88,7 +86,7 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateUp: () -> Unit) {
|
||||
if (isVerticalLayout()) {
|
||||
TopBar {
|
||||
TypeCard(types = uiState.currentTypes, toggleDialog, modifier = Modifier.weight(1f))
|
||||
SaveButton(saveSelection = saveSelection, modifier = Modifier.height(48.dp))
|
||||
PrimaryIconCard(onClick = saveSelection, resId = R.drawable.ic_done)
|
||||
}
|
||||
TopBar {
|
||||
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
|
||||
@@ -97,7 +95,7 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateUp: () -> Unit) {
|
||||
}
|
||||
} else {
|
||||
TopBar {
|
||||
SaveButton(saveSelection = saveSelection, modifier = Modifier.height(48.dp))
|
||||
PrimaryIconCard(onClick = saveSelection, resId = R.drawable.ic_done)
|
||||
TypeCard(types = uiState.currentTypes, toggleDialog, modifier = Modifier.weight(1f))
|
||||
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
|
||||
IconCard(action = unselectAll, resId = R.drawable.ic_check_off)
|
||||
@@ -163,19 +161,6 @@ private fun SearchBar(setQuery: (String) -> Unit, modifier: Modifier = Modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SaveButton(saveSelection: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val clickableModifier = modifier.clickable { saveSelection() }
|
||||
ElevatedCard(
|
||||
modifier = Modifier.width(102.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary)
|
||||
) {
|
||||
Box(modifier = clickableModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Icon(painter = painterResource(id = R.drawable.ic_done), contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeCard(types: List<String>, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val typesText = if (types.isEmpty()) "All" else types.joinToString(", ")
|
||||
@@ -187,7 +172,11 @@ private fun TypeCard(types: List<String>, onClick: () -> Unit, modifier: Modifie
|
||||
.height(48.dp)
|
||||
.clickable { onClick() }) {
|
||||
Spacer(Modifier)
|
||||
Icon(painter = painterResource(id = R.drawable.ic_tags), contentDescription = null)
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_tags),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = "Tags: $typesText",
|
||||
fontSize = 16.sp,
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.Manifest
|
||||
import android.os.Build
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -11,7 +12,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
@@ -27,6 +27,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -45,7 +46,11 @@ import com.rtbishop.look4sat.domain.predict.GeoPos
|
||||
import com.rtbishop.look4sat.presentation.MainTheme
|
||||
import com.rtbishop.look4sat.presentation.Screen
|
||||
import com.rtbishop.look4sat.presentation.common.CardButton
|
||||
import com.rtbishop.look4sat.presentation.common.layoutPadding
|
||||
import com.rtbishop.look4sat.presentation.common.IconCard
|
||||
import com.rtbishop.look4sat.presentation.common.PrimaryIconCard
|
||||
import com.rtbishop.look4sat.presentation.common.ScreenColumn
|
||||
import com.rtbishop.look4sat.presentation.common.TopBar
|
||||
import com.rtbishop.look4sat.presentation.common.infiniteMarquee
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
@@ -61,9 +66,6 @@ fun NavGraphBuilder.settingsDestination() {
|
||||
}
|
||||
}
|
||||
|
||||
private const val POLICY_URL = "https://sites.google.com/view/look4sat-privacy-policy/home"
|
||||
private const val LICENSE_URL = "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
|
||||
@Composable
|
||||
private fun SettingsScreen(uiState: SettingsState) {
|
||||
// Permissions setup
|
||||
@@ -127,99 +129,64 @@ private fun SettingsScreen(uiState: SettingsState) {
|
||||
val toggleUpdate = { value: Boolean -> uiState.sendAction(SettingsAction.ToggleUpdate(value)) }
|
||||
val toggleSweep = { value: Boolean -> uiState.sendAction(SettingsAction.ToggleSweep(value)) }
|
||||
val toggleSensor = { value: Boolean -> uiState.sendAction(SettingsAction.ToggleSensor(value)) }
|
||||
val toggleLightTheme = { value: Boolean ->
|
||||
uiState.sendAction(SettingsAction.ToggleLightTheme(value))
|
||||
}
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
// Screen setup
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(320.dp),
|
||||
modifier = Modifier.layoutPadding(),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||
) {
|
||||
item { CardAbout(uiState.appVersionName, uiState.sendSystemAction) }
|
||||
item {
|
||||
LocationCard(
|
||||
positionSettings,
|
||||
setGpsPos,
|
||||
showPosDialog,
|
||||
showLocDialog,
|
||||
dismissPos,
|
||||
uiState.sendSystemAction
|
||||
)
|
||||
}
|
||||
item { DataCard(dataSettings, updateFromWeb, updateFromFile, clearAllData) }
|
||||
item {
|
||||
OtherCard(
|
||||
otherSettings,
|
||||
toggleUtc,
|
||||
toggleUpdate,
|
||||
toggleSweep,
|
||||
toggleSensor,
|
||||
toggleLightTheme
|
||||
)
|
||||
}
|
||||
item { CardCredits() }
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun CardAboutPreview() = MainTheme { CardAbout(version = "4.0.0") }
|
||||
|
||||
@Composable
|
||||
private fun CardAbout(version: String, sendUrlAction: (SystemAction) -> Unit = {}) {
|
||||
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_satellites),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(72.dp)
|
||||
)
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_name),
|
||||
fontSize = 48.sp,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_version, version), fontSize = 20.sp
|
||||
)
|
||||
ScreenColumn(
|
||||
topBar = { isVerticalLayout ->
|
||||
if (isVerticalLayout) {
|
||||
TopBar {
|
||||
TopCard(onClick = { uriHandler.openUri("https://play.google.com/store/apps/details?id=com.rtbishop.look4sat") }, version = uiState.appVersionName, modifier = Modifier.weight(1f))
|
||||
PrimaryIconCard(onClick = { uriHandler.openUri("https://ko-fi.com/rt_bishop") }, resId = R.drawable.ic_pound)
|
||||
}
|
||||
TopBar {
|
||||
Row(modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
BotCard(onClick = { uriHandler.openUri("https://www.gnu.org/licenses/gpl-3.0.html") }, R.drawable.ic_license, "Licence", modifier = Modifier.weight(1f))
|
||||
BotCard(onClick = { uriHandler.openUri("https://sites.google.com/view/look4sat-privacy-policy/home") }, R.drawable.ic_policy, "Privacy", modifier = Modifier.weight(1f))
|
||||
}
|
||||
IconCard(action = { uriHandler.openUri("https://f-droid.org/en/packages/com.rtbishop.look4sat/") }, resId = R.drawable.ic_fdroid)
|
||||
IconCard(action = { uriHandler.openUri("https://github.com/rt-bishop/Look4Sat/") }, resId = R.drawable.ic_github)
|
||||
}
|
||||
} else {
|
||||
TopBar {
|
||||
PrimaryIconCard(onClick = { uriHandler.openUri("https://ko-fi.com/rt_bishop") }, resId = R.drawable.ic_pound)
|
||||
TopCard(onClick = { uriHandler.openUri("https://play.google.com/store/apps/details?id=com.rtbishop.look4sat") }, version = uiState.appVersionName, modifier = Modifier.weight(1f))
|
||||
Row(modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
BotCard(onClick = { uriHandler.openUri("https://www.gnu.org/licenses/gpl-3.0.html") }, R.drawable.ic_license, "Licence", modifier = Modifier.weight(1f))
|
||||
BotCard(onClick = { uriHandler.openUri("https://sites.google.com/view/look4sat-privacy-policy/home") }, R.drawable.ic_policy, "Privacy", modifier = Modifier.weight(1f))
|
||||
}
|
||||
IconCard(action = { uriHandler.openUri("https://f-droid.org/en/packages/com.rtbishop.look4sat/") }, resId = R.drawable.ic_fdroid)
|
||||
IconCard(action = { uriHandler.openUri("https://github.com/rt-bishop/Look4Sat/") }, resId = R.drawable.ic_github)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = stringResource(id = R.string.app_subtitle),
|
||||
fontSize = 20.sp,
|
||||
modifier = Modifier.padding(top = 4.dp, bottom = 2.dp)
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
|
||||
CardButton(
|
||||
onClick = { sendUrlAction(SystemAction.OpenGitHub) },
|
||||
text = stringResource(id = R.string.btn_github),
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
CardButton(
|
||||
onClick = { sendUrlAction(SystemAction.OpenDonate) },
|
||||
text = stringResource(id = R.string.btn_donate),
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
CardButton(
|
||||
onClick = { sendUrlAction(SystemAction.OpenFDroid) },
|
||||
text = stringResource(id = R.string.btn_fdroid),
|
||||
modifier = Modifier.weight(1f)
|
||||
}
|
||||
) { _ ->
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(320.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
modifier = Modifier.clip(MaterialTheme.shapes.medium)
|
||||
) {
|
||||
item {
|
||||
LocationCard(
|
||||
positionSettings,
|
||||
setGpsPos,
|
||||
showPosDialog,
|
||||
showLocDialog,
|
||||
dismissPos,
|
||||
uiState.sendSystemAction
|
||||
)
|
||||
}
|
||||
item { DataCard(dataSettings, updateFromWeb, updateFromFile, clearAllData) }
|
||||
item {
|
||||
OtherCard(
|
||||
otherSettings,
|
||||
toggleUtc,
|
||||
toggleUpdate,
|
||||
toggleSweep,
|
||||
toggleSensor
|
||||
)
|
||||
}
|
||||
item { CardCredits() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,7 +386,7 @@ private fun OtherCardPreview() = MainTheme {
|
||||
shouldSeeWarning = false,
|
||||
shouldSeeWelcome = false
|
||||
)
|
||||
OtherCard(settings = values, {}, {}, {}, {}, {})
|
||||
OtherCard(settings = values, {}, {}, {}, {})
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -428,8 +395,7 @@ private fun OtherCard(
|
||||
toggleUtc: (Boolean) -> Unit,
|
||||
toggleUpdate: (Boolean) -> Unit,
|
||||
toggleSweep: (Boolean) -> Unit,
|
||||
toggleSensor: (Boolean) -> Unit,
|
||||
toggleLightTheme: (Boolean) -> Unit
|
||||
toggleSensor: (Boolean) -> Unit
|
||||
) {
|
||||
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp)) {
|
||||
@@ -465,17 +431,6 @@ private fun OtherCard(
|
||||
Text(text = stringResource(id = R.string.other_switch_sensors))
|
||||
Switch(checked = settings.stateOfSensors, onCheckedChange = { toggleSensor(it) })
|
||||
}
|
||||
// Row(
|
||||
// horizontalArrangement = Arrangement.SpaceBetween,
|
||||
// verticalAlignment = Alignment.CenterVertically,
|
||||
// modifier = Modifier.fillMaxWidth()
|
||||
// ) {
|
||||
// Text(text = stringResource(id = R.string.other_switch_light_theme))
|
||||
// Switch(
|
||||
// checked = settings.stateOfLightTheme,
|
||||
// onCheckedChange = { toggleLightTheme(it) }
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -508,7 +463,6 @@ private fun CardCreditsPreview() = MainTheme { CardCredits() }
|
||||
|
||||
@Composable
|
||||
private fun CardCredits(modifier: Modifier = Modifier) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
ElevatedCard(modifier = modifier.fillMaxWidth()) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
@@ -533,19 +487,58 @@ private fun CardCredits(modifier: Modifier = Modifier) {
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = modifier.padding(6.dp)
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
|
||||
CardButton(
|
||||
onClick = { uriHandler.openUri(LICENSE_URL) },
|
||||
text = stringResource(id = R.string.btn_license),
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
CardButton(
|
||||
onClick = { uriHandler.openUri(POLICY_URL) },
|
||||
text = stringResource(id = R.string.btn_privacy),
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TopCard(onClick: () -> Unit, modifier: Modifier = Modifier, version: String) {
|
||||
ElevatedCard(modifier = modifier) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.clickable { onClick() }) {
|
||||
Spacer(Modifier)
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_satellites),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = "Look4Sat v$version",
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(end = 6.dp)
|
||||
.infiniteMarquee()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BotCard(onClick: () -> Unit, resId: Int, text: String, modifier: Modifier = Modifier) {
|
||||
ElevatedCard(modifier = modifier) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.clickable { onClick() }) {
|
||||
Spacer(Modifier)
|
||||
Icon(painter = painterResource(id = resId), contentDescription = null)
|
||||
Text(
|
||||
text = text,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(end = 6.dp)
|
||||
.infiniteMarquee()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.rtbishop.look4sat.presentation.settings
|
||||
|
||||
import com.rtbishop.look4sat.domain.model.OtherSettings
|
||||
import com.rtbishop.look4sat.domain.predict.GeoPos
|
||||
import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
||||
|
||||
data class PositionSettings(
|
||||
val isUpdating: Boolean, val stationPos: GeoPos, val messageResId: Int
|
||||
@@ -22,6 +23,9 @@ data class RCSettings(
|
||||
)
|
||||
|
||||
data class SettingsState(
|
||||
val nextPass: OrbitalPass,
|
||||
val nextTime: String,
|
||||
val isNextTimeAos: Boolean,
|
||||
val appVersionName: String,
|
||||
val positionSettings: PositionSettings,
|
||||
val dataSettings: DataSettings,
|
||||
|
||||
+46
-12
@@ -24,26 +24,31 @@ import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.rtbishop.look4sat.MainApplication
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
||||
import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||
import com.rtbishop.look4sat.domain.usecase.IOpenWebUrl
|
||||
import com.rtbishop.look4sat.domain.usecase.IShowToast
|
||||
import com.rtbishop.look4sat.domain.utility.toTimerString
|
||||
import com.rtbishop.look4sat.presentation.common.getDefaultPass
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SettingsViewModel(
|
||||
private val databaseRepo: IDatabaseRepo,
|
||||
private val satelliteRepo: ISatelliteRepo,
|
||||
private val settingsRepo: ISettingsRepo,
|
||||
private val openWebUrl: IOpenWebUrl,
|
||||
private val showToast: IShowToast,
|
||||
appVersionName: String
|
||||
) : ViewModel() {
|
||||
|
||||
private val githubUrl = "https://github.com/rt-bishop/Look4Sat/"
|
||||
private val donateUrl = "https://ko-fi.com/rt_bishop"
|
||||
private val fdroidUrl = "https://f-droid.org/en/packages/com.rtbishop.look4sat/"
|
||||
private val defaultPosSettings = PositionSettings(false, settingsRepo.stationPosition.value, 0)
|
||||
private val defaultDataSettings = DataSettings(false, 0, 0, 0L)
|
||||
private val defaultRCSettings = RCSettings(
|
||||
@@ -57,6 +62,9 @@ class SettingsViewModel(
|
||||
)
|
||||
private val _uiState = MutableStateFlow(
|
||||
SettingsState(
|
||||
nextTime = "00:00:00",
|
||||
isNextTimeAos = true,
|
||||
nextPass = getDefaultPass(),
|
||||
appVersionName = appVersionName,
|
||||
positionSettings = defaultPosSettings,
|
||||
dataSettings = defaultDataSettings,
|
||||
@@ -67,9 +75,24 @@ class SettingsViewModel(
|
||||
sendSystemAction = ::handleAction
|
||||
)
|
||||
)
|
||||
private var processing: Job? = null
|
||||
|
||||
val uiState: StateFlow<SettingsState> = _uiState
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
satelliteRepo.passes.collectLatest { passes ->
|
||||
processing?.cancelAndJoin()
|
||||
processing = viewModelScope.launch {
|
||||
while (isActive) {
|
||||
val timeNow = System.currentTimeMillis()
|
||||
val newPasses = satelliteRepo.processPasses(passes, timeNow)
|
||||
setPassInfo(newPasses, timeNow)
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
settingsRepo.stationPosition.collect { geoPos ->
|
||||
val newPosSettings = _uiState.value.positionSettings.copy(
|
||||
@@ -127,15 +150,13 @@ class SettingsViewModel(
|
||||
|
||||
private fun handleAction(action: SystemAction) {
|
||||
when (action) {
|
||||
SystemAction.OpenGitHub -> openWebUrl(githubUrl)
|
||||
SystemAction.OpenDonate -> openWebUrl(donateUrl)
|
||||
SystemAction.OpenFDroid -> openWebUrl(fdroidUrl)
|
||||
is SystemAction.ShowToast -> showToast(action.message)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setGpsPosition() {
|
||||
if (settingsRepo.setStationPositionGps()) {
|
||||
if (settingsRepo.setStationPosition()) {
|
||||
val messageResId = R.string.location_success
|
||||
val newPosSettings = _uiState.value.positionSettings.copy(
|
||||
isUpdating = true, messageResId = messageResId
|
||||
@@ -151,7 +172,7 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun setGeoPosition(latitude: Double, longitude: Double) {
|
||||
if (settingsRepo.setStationPositionGeo(latitude, longitude, 0.0)) {
|
||||
if (settingsRepo.setStationPosition(latitude, longitude, 0.0)) {
|
||||
val messageResId = R.string.location_success
|
||||
val newPosSettings = _uiState.value.positionSettings.copy(
|
||||
isUpdating = false, messageResId = messageResId
|
||||
@@ -167,7 +188,7 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun setQthPosition(locator: String) {
|
||||
if (settingsRepo.setStationPositionQth(locator)) {
|
||||
if (settingsRepo.setStationPosition(locator)) {
|
||||
val messageResId = R.string.location_success
|
||||
val newPosSettings = _uiState.value.positionSettings.copy(
|
||||
isUpdating = false, messageResId = messageResId
|
||||
@@ -213,6 +234,19 @@ class SettingsViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private fun setPassInfo(passes: List<OrbitalPass>, timeNow: Long) {
|
||||
if (passes.isEmpty()) return
|
||||
try {
|
||||
val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 }
|
||||
val time = nextPass.aosTime.minus(timeNow).toTimerString()
|
||||
_uiState.update { it.copy(nextPass = nextPass, nextTime = time, isNextTimeAos = true) }
|
||||
} catch (_: NoSuchElementException) {
|
||||
val lastPass = passes.last()
|
||||
val time = lastPass.losTime.minus(timeNow).toTimerString()
|
||||
_uiState.update { it.copy(nextPass = lastPass, nextTime = time, isNextTimeAos = false) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearAllData() = viewModelScope.launch { databaseRepo.clearAllData() }
|
||||
|
||||
companion object {
|
||||
@@ -222,8 +256,8 @@ class SettingsViewModel(
|
||||
val container = (this[applicationKey] as MainApplication).container
|
||||
SettingsViewModel(
|
||||
container.databaseRepo,
|
||||
container.satelliteRepo,
|
||||
container.settingsRepo,
|
||||
container.provideOpenWebUrl(),
|
||||
container.provideShowToast(),
|
||||
container.provideAppVersionName()
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user