Fixes and refactoring for SettingsScreen

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:33 +00:00
1 parent f7f317cf8b
commit 12fabc8f23
16 files changed
+225 -174

No files matched your search

+4 -3
View File
@@ -13,7 +13,7 @@
<application
android:name=".MainApplication"
android:allowBackup="true"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
@@ -26,12 +26,13 @@
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.Look4Sat.SplashScreen">
android:screenOrientation="portrait"
android:theme="@style/Theme.Look4Sat.SplashScreen"
tools:ignore="LockedOrientationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -18,7 +18,6 @@
package com.rtbishop.look4sat
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Bundle
import androidx.activity.ComponentActivity
@@ -32,15 +31,13 @@ import dagger.hilt.android.AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
installSplashScreen()
super.onCreate(savedInstanceState)
setContent { MainTheme { MainScreen() } }
}
override fun attachBaseContext(newBase: Context?) {
val newConfig = Configuration(newBase?.resources?.configuration)
newConfig.fontScale = 1.0f
val newConfig = Configuration(newBase?.resources?.configuration).apply { fontScale = 1.0f }
applyOverrideConfiguration(newConfig)
super.attachBaseContext(newBase)
}
@@ -17,6 +17,7 @@
*/
package com.rtbishop.look4sat.framework
import android.location.Criteria
import android.location.Location
import android.location.LocationManager
import androidx.core.location.LocationListenerCompat
@@ -35,13 +36,15 @@ class LocationSource(
private val settings: ISettingsSource,
) : ILocationSource, LocationListenerCompat {
private val defaultProvider = LocationManager.PASSIVE_PROVIDER
private val _stationPosition = MutableStateFlow(settings.loadStationPosition())
override val stationPosition: StateFlow<StationPos> = _stationPosition
override fun setGpsPosition(): Boolean {
if (!LocationManagerCompat.isLocationEnabled(manager)) return false
forceLocationUpdate(LocationManager.GPS_PROVIDER)
forceLocationUpdate(LocationManager.NETWORK_PROVIDER)
val criteria = Criteria().apply { isCostAllowed = true }
val bestProvider = manager.getBestProvider(criteria, true) ?: defaultProvider
forceLocationUpdate(bestProvider)
return true
}
@@ -65,7 +68,7 @@ class LocationSource(
private fun forceLocationUpdate(provider: String) {
try {
val location = manager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)
val location = manager.getLastKnownLocation(defaultProvider)
if (location == null || System.currentTimeMillis() - location.time > 600000) {
Timber.d("Requesting $provider location update")
manager.requestLocationUpdates(provider, 0L, 0f, this)
@@ -50,7 +50,7 @@ class SettingsSource(private val prefs: SharedPreferences) : ISettingsSource {
override fun loadStationPosition(): StationPos {
val latitude = prefs.getString(keyLatitude, null) ?: "0.0"
val longitude = prefs.getString(keyLongitude, null) ?: "0.0"
val qthLocator = prefs.getString(keyLocator, null) ?: ""
val qthLocator = prefs.getString(keyLocator, null) ?: "null"
val timestamp = prefs.getLong(keyLocTimestamp, 0L)
return StationPos(latitude.toDouble(), longitude.toDouble(), qthLocator, timestamp)
}
@@ -9,7 +9,6 @@ import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
@@ -28,7 +27,7 @@ fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier)
onClick = { onClick() }, colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.tertiary,
contentColor = MaterialTheme.colorScheme.onTertiary
), shape = MaterialTheme.shapes.small, modifier = modifier.padding(start = 4.dp, end = 4.dp)
), shape = MaterialTheme.shapes.small, modifier = modifier
) { Text(text = text, fontSize = 17.sp) }
}
@@ -60,14 +60,18 @@ private fun MainNavBar(navController: NavController) {
@Composable
private fun MainNavGraph(navController: NavHostController) {
val navToPasses = { navController.navigate(Screen.Passes.route) }
val navToRadar = { catNum: Int, aosTime: Long ->
navController.navigate("${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}")
}
val radarRoute = "${Screen.Radar.route}?catNum={catNum}&aosTime={aosTime}"
val radarArgs = listOf(navArgument("catNum") { defaultValue = 0 },
navArgument("aosTime") { defaultValue = 0L })
NavHost(navController, startDestination = Screen.Passes.route) {
composable(Screen.Entries.route) { EntriesScreen(navController) }
composable(Screen.Passes.route) { PassesScreen(navController) }
composable(radarRoute, radarArgs) { RadarScreen(navController) }
composable(Screen.Entries.route) { EntriesScreen(navToPasses) }
composable(Screen.Passes.route) { PassesScreen(navToRadar) }
composable(radarRoute, radarArgs) { RadarScreen() }
composable(Screen.Map.route) { MapScreen() }
composable(Screen.Settings.route) { SettingsScreen(navController) }
composable(Screen.Settings.route) { SettingsScreen() }
}
}
@@ -26,21 +26,17 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.DataState
import com.rtbishop.look4sat.model.SatItem
import com.rtbishop.look4sat.presentation.CardLoadingIndicator
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.dialogs.TypesDialog
import com.rtbishop.look4sat.presentation.onClick
@Composable
fun EntriesScreen(navController: NavController) {
val viewModel: EntriesViewModel = hiltViewModel()
fun EntriesScreen(navToPasses: () -> Unit, viewModel: EntriesViewModel = hiltViewModel()) {
val state = viewModel.satData.collectAsState(initial = DataState.Loading)
val navToPasses = { navController.navigate(Screen.Passes.route) }
val showDialog = rememberSaveable { mutableStateOf(false) }
val toggleDialog = { showDialog.value = showDialog.value.not() }
@@ -102,8 +102,8 @@ private fun setPositions(
posMap: Map<Satellite, GeoPos>, mapView: MapView, action: (Satellite) -> Unit
) {
val markers = FolderOverlay()
posMap.entries.forEach {
try {
posMap.entries.forEach {
Marker(mapView).apply {
setInfoWindow(null)
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
@@ -119,12 +119,12 @@ private fun setPositions(
}
markers.add(this)
}
} catch (exception: Exception) {
Timber.d(exception)
}
}
mapView.overlays[3] = markers
mapView.invalidate()
} catch (exception: Exception) {
Timber.d(exception)
}
}
private fun getCustomTextIcon(textLabel: String, mapView: MapView): Drawable {
@@ -143,33 +143,33 @@ private fun getCustomTextIcon(textLabel: String, mapView: MapView): Drawable {
private fun setSatelliteTrack(satTrack: List<List<GeoPos>>, mapView: MapView) {
// val center = GeoPoint(satTrack[0][0].lat, satTrack[0][0].lon)
val trackOverlay = FolderOverlay()
try {
satTrack.forEach { track ->
val trackPoints = track.map { GeoPoint(it.lat, it.lon) }
Polyline().apply {
try {
setPoints(trackPoints)
outlinePaint.set(trackPaint)
trackOverlay.add(this)
} catch (exception: IllegalArgumentException) {
println(exception.stackTraceToString())
}
}
}
mapView.overlays[1] = trackOverlay
} catch (exception: Exception) {
Timber.d(exception)
}
// mapView.controller.animateTo(center)
}
private fun setFootprint(satPos: SatPos, mapView: MapView) {
val footprintPoints = satPos.getRangeCircle().map { GeoPoint(it.lat, it.lon) }
try {
val footprintOverlay = Polyline().apply {
outlinePaint.set(footprintPaint)
try {
setPoints(footprintPoints)
} catch (exception: IllegalArgumentException) {
println(exception.stackTraceToString())
}
}
mapView.overlays[2] = footprintOverlay
} catch (exception: Exception) {
Timber.d(exception)
}
}
//private fun handleMapData(mapData: MapData) {
@@ -21,7 +21,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.*
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.NearEarthSat
import com.rtbishop.look4sat.model.DataState
@@ -39,11 +38,7 @@ import java.util.*
private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
@Composable
fun PassesScreen(navController: NavController) {
val viewModel: PassesViewModel = hiltViewModel()
val navToRadar = { catNum: Int, aosTime: Long ->
navController.navigate("${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}")
}
fun PassesScreen(navToRadar: (Int, Long) -> Unit, viewModel: PassesViewModel = hiltViewModel()) {
val state = viewModel.passes.collectAsState(initial = null)
val timerText = viewModel.timerText.collectAsState(initial = null)
val isRefreshing = state.value is DataState.Loading
@@ -185,7 +180,6 @@ private fun Pass(pass: SatPass, navToRadar: (Int, Long) -> Unit, modifier: Modif
modifier = modifier
.fillMaxWidth(0.75f)
.padding(top = 3.dp),
color = MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.inverseSurface
)
Text(
@@ -16,13 +16,11 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.SatRadio
@Composable
fun RadarScreen(navController: NavController) {
val viewModel: RadarViewModel = hiltViewModel()
fun RadarScreen(viewModel: RadarViewModel = hiltViewModel()) {
val currentPass = viewModel.getPass().collectAsState(null)
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
@@ -21,15 +21,17 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.rtbishop.look4sat.BuildConfig
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.StationPos
import com.rtbishop.look4sat.presentation.CardButton
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.dialogs.LocatorDialog
import com.rtbishop.look4sat.presentation.dialogs.PositionDialog
import com.rtbishop.look4sat.presentation.gotoUrl
import com.rtbishop.look4sat.presentation.showToast
import java.text.SimpleDateFormat
import java.util.*
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"
@@ -38,9 +40,8 @@ private const val DONATE_URL = "https://ko-fi.com/rt_bishop"
private const val FDROID_URL = "https://f-droid.org/en/packages/com.rtbishop.look4sat/"
@Composable
fun SettingsScreen(navController: NavController) {
fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel()) {
val context = LocalContext.current
val viewModel: SettingsViewModel = hiltViewModel()
// Permissions setup
val bluetoothContract = ActivityResultContracts.RequestPermission()
@@ -76,8 +77,8 @@ fun SettingsScreen(navController: NavController) {
val togglePosDialog = { showPosDialog.value = showPosDialog.value.not() }
if (showPosDialog.value) {
PositionDialog(
locSettings.getLatitude,
locSettings.getLongitude,
locSettings.stationPos.latitude,
locSettings.stationPos.longitude,
togglePosDialog,
locSettings.setManualLoc
)
@@ -85,7 +86,7 @@ fun SettingsScreen(navController: NavController) {
val showLocDialog = rememberSaveable { mutableStateOf(false) }
val toggleLocDialog = { showLocDialog.value = showLocDialog.value.not() }
if (showLocDialog.value) {
LocatorDialog(locSettings.getLocator, toggleLocDialog, locSettings.setQthLoc)
LocatorDialog(locSettings.stationPos.qthLocator, toggleLocDialog, locSettings.setQthLoc)
}
// Screen setup
@@ -100,11 +101,18 @@ fun SettingsScreen(navController: NavController) {
}
}
@Preview(showBackground = true)
@Composable
private fun CardAboutPreview() = MainTheme { CardAbout(version = "4.0.0") }
@Composable
private fun CardAbout(version: String, modifier: Modifier = Modifier) {
val context = LocalContext.current
ElevatedCard(modifier = modifier.fillMaxWidth()) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Row(horizontalArrangement = Arrangement.Center) {
Icon(
painter = painterResource(id = R.drawable.ic_entries),
@@ -128,21 +136,21 @@ private fun CardAbout(version: String, modifier: Modifier = Modifier) {
Text(
text = stringResource(id = R.string.app_subtitle),
fontSize = 20.sp,
modifier = modifier.padding(top = 4.dp)
modifier = modifier.padding(top = 4.dp, bottom = 2.dp)
)
Row(
horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.padding(4.dp)
) {
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = { gotoUrl(context, GITHUB_URL) },
text = stringResource(id = R.string.btn_github),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = { gotoUrl(context, DONATE_URL) },
text = stringResource(id = R.string.btn_donate),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = { gotoUrl(context, FDROID_URL) },
text = stringResource(id = R.string.btn_fdroid),
@@ -155,8 +163,11 @@ private fun CardAbout(version: String, modifier: Modifier = Modifier) {
@Preview(showBackground = true)
@Composable
private fun LocationCardPreview() {
MainTheme { }
private fun LocationCardPreview() = MainTheme {
val stationPos = StationPos(0.0, 0.0, "IO91vl", 0L)
LocationCard(
settings = LocationSettings(true, stationPos, {}, { _, _ -> }, { }),
setGpsLoc = {}, togglePosDialog = {}) {}
}
@Composable
@@ -167,36 +178,56 @@ private fun LocationCard(
toggleLocDialog: () -> Unit
) {
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(4.dp)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Station position")
UpdateIndicator(isUpdating = settings.getUpdating, Modifier.weight(1f))
Text(
text = stringResource(id = R.string.location_title),
color = MaterialTheme.colorScheme.primary
)
UpdateIndicator(isUpdating = settings.isUpdating, Modifier.weight(1f))
}
Row(
horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()
) {
Text(text = "Updated: ${settings.getLastUpdated}")
Text(text = "QTH: ${settings.getLocator}")
}
Row(
horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()
) {
Text(text = "Latitude: ${settings.getLatitude}")
Text(text = "Longitude: ${settings.getLongitude}")
Spacer(modifier = Modifier.height(2.dp))
Text(text = setUpdateTime(updateTime = settings.stationPos.timestamp))
Spacer(modifier = Modifier.height(2.dp))
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Text(
text = "Lat: ${settings.stationPos.latitude}°",
modifier = Modifier.weight(1f),
textAlign = TextAlign.Start
)
Text(
text = "Lon: ${settings.stationPos.longitude}°",
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center
)
Text(
text = "Qth: ${settings.stationPos.qthLocator}",
modifier = Modifier.weight(1f),
textAlign = TextAlign.End
)
}
Spacer(modifier = Modifier.height(1.dp))
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = setGpsLoc, // locationRequest.launch(arrayOf(locationFine, locationCoarse))
text = stringResource(id = R.string.btn_gps), modifier = Modifier.weight(1f)
onClick = setGpsLoc,
text = stringResource(id = R.string.btn_gps),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = togglePosDialog, // open Position dialog
text = stringResource(id = R.string.btn_manual), modifier = Modifier.weight(1f)
) // viewModel.setStationPosition(position.first, position.second)
onClick = togglePosDialog,
text = stringResource(id = R.string.btn_manual),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = toggleLocDialog, // open Locator dialog
text = stringResource(id = R.string.btn_qth), modifier = Modifier.weight(1f)
) // viewModel.setPositionFromQth(locator)
onClick = toggleLocDialog,
text = stringResource(id = R.string.btn_qth),
modifier = Modifier.weight(1f)
)
}
}
}
@@ -204,42 +235,52 @@ private fun LocationCard(
@Preview(showBackground = true)
@Composable
private fun DataCardPreview() {
MainTheme { }
private fun DataCardPreview() = MainTheme {
DataCard(settings = DataSettings(
true, 0L, 5000, 2500, {}, { }, {})
) {}
}
@Composable
private fun DataCard(settings: DataSettings, updateFromFile: () -> Unit) {
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(4.dp)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Satellite data")
UpdateIndicator(isUpdating = settings.getUpdating, Modifier.weight(1f))
Text(
text = stringResource(id = R.string.data_title),
color = MaterialTheme.colorScheme.primary
)
UpdateIndicator(isUpdating = settings.isUpdating, Modifier.weight(1f))
}
Row(
horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()
) {
Text(text = "Updated: ${settings.getLastUpdated}")
Text(text = "")
}
Row(
horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()
) {
Text(text = "Satellites: ${settings.getSatellites}")
Text(text = "Transceivers: ${settings.getRadios}")
Spacer(modifier = Modifier.height(2.dp))
Text(text = setUpdateTime(updateTime = settings.lastUpdated))
Spacer(modifier = Modifier.height(2.dp))
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Text(text = "Satellites: ${settings.satsTotal}")
Spacer(modifier = Modifier.weight(1f))
Text(text = "Transceivers: ${settings.radiosTotal}")
}
Spacer(modifier = Modifier.height(1.dp))
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = settings.updateFromWeb, // viewModel.updateFromWeb()
text = stringResource(id = R.string.btn_web), modifier = Modifier.weight(1f)
onClick = settings.updateFromWeb,
text = stringResource(id = R.string.btn_web),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = updateFromFile, // contentRequest.launch("*/*")
text = stringResource(id = R.string.btn_file), modifier = Modifier.weight(1f)
onClick = updateFromFile,
text = stringResource(id = R.string.btn_file),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = settings.clearAllData, // viewModel.clearAllData()
text = stringResource(id = R.string.btn_clear), modifier = Modifier.weight(1f)
onClick = settings.clearAllData,
text = stringResource(id = R.string.btn_clear),
modifier = Modifier.weight(1f)
)
}
}
@@ -293,15 +334,17 @@ private fun DataCard(settings: DataSettings, updateFromFile: () -> Unit) {
//
@Preview(showBackground = true)
@Composable
private fun OtherCardPreview() {
MainTheme { }
private fun OtherCardPreview() = MainTheme {
OtherCard(settings = OtherSettings(
getUtc = false, getUpdate = true, getSweep = true, getSensor = true,
setUtc = {}, setUpdate = {}, setSweep = {}, setSensor = {})
)
}
@Composable
private fun OtherCard(settings: OtherSettings) {
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(4.dp)) {
Text(text = stringResource(id = R.string.other_title))
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp)) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@@ -309,7 +352,7 @@ private fun OtherCard(settings: OtherSettings) {
) {
Text(text = stringResource(id = R.string.other_switch_utc))
Switch(checked = settings.getUtc, onCheckedChange = { settings.setUtc(it) })
} // viewModel.setUseUTC(isChecked)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@@ -317,7 +360,7 @@ private fun OtherCard(settings: OtherSettings) {
) {
Text(text = stringResource(id = R.string.other_switch_update))
Switch(checked = settings.getUpdate, onCheckedChange = { settings.setUpdate(it) })
} // AutoUpdateEnabled(isChecked)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@@ -325,7 +368,7 @@ private fun OtherCard(settings: OtherSettings) {
) {
Text(text = stringResource(id = R.string.other_switch_sweep))
Switch(checked = settings.getSweep, onCheckedChange = { settings.setSweep(it) })
} // viewModel.setShowSweep(isChecked)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@@ -333,58 +376,49 @@ private fun OtherCard(settings: OtherSettings) {
) {
Text(text = stringResource(id = R.string.other_switch_sensors))
Switch(checked = settings.getSensor, onCheckedChange = { settings.setSensor(it) })
} // viewModel.setUseCompass(isChecked)
}
}
}
}
//
// showToast(getString(R.string.data_clear_success))
// showToast(getString(R.string.data_success))
//
//private fun setUpdateTime(updateTime: Long) {
// val updatePattern = getString(R.string.data_update)
// val updateDate = if (updateTime == 0L) {
// getString(R.string.pass_placeholder)
// } else {
// SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault()).format(Date(updateTime))
// }
// binding.settingsData.dataUpdate.text = String.format(updatePattern, updateDate)
//}
//
@Preview(showBackground = true)
@Composable
private fun CardCreditsPreview() = MainTheme { CardCredits() }
@Composable
private fun CardCredits(modifier: Modifier = Modifier) {
val context = LocalContext.current
ElevatedCard(modifier = modifier.fillMaxWidth()) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Text(
text = stringResource(id = R.string.outro_title),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.secondary,
modifier = modifier.padding(8.dp)
modifier = modifier.padding(6.dp)
)
Text(
text = stringResource(id = R.string.outro_thanks),
fontSize = 16.sp,
textAlign = TextAlign.Center,
modifier = modifier.padding(horizontal = 6.dp, vertical = 4.dp)
textAlign = TextAlign.Center
)
Text(
text = stringResource(id = R.string.outro_license),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.secondary,
modifier = modifier.padding(8.dp)
modifier = modifier.padding(6.dp)
)
Row(
horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.padding(4.dp)
) {
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = { gotoUrl(context, LICENSE_URL) },
text = stringResource(id = R.string.btn_license),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = { gotoUrl(context, POLICY_URL) },
text = stringResource(id = R.string.btn_privacy),
@@ -396,8 +430,26 @@ private fun CardCredits(modifier: Modifier = Modifier) {
}
@Composable
private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier) = if (isUpdating) {
LinearProgressIndicator(modifier = modifier.padding(start = 6.dp, end = 6.dp))
private fun setUpdateTime(updateTime: Long): String {
val updateDate = if (updateTime != 0L) {
val timePattern = stringResource(id = R.string.last_updated_pattern)
SimpleDateFormat(timePattern, Locale.getDefault()).format(Date(updateTime))
} else {
LinearProgressIndicator(modifier = modifier.padding(start = 6.dp, end = 6.dp), progress = 0f)
stringResource(id = R.string.pass_placeholder)
}
return stringResource(id = R.string.data_update, updateDate)
}
@Composable
private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier) = if (isUpdating) {
LinearProgressIndicator(
modifier = modifier.padding(start = 6.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface
)
} else {
LinearProgressIndicator(
progress = 0f,
modifier = modifier.padding(start = 6.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface
)
}
@@ -1,21 +1,20 @@
package com.rtbishop.look4sat.presentation.settings
import com.rtbishop.look4sat.model.StationPos
data class LocationSettings(
val getUpdating: Boolean,
val getLastUpdated: Long,
val getLatitude: Double,
val getLongitude: Double,
val getLocator: String,
val isUpdating: Boolean,
val stationPos: StationPos,
val setGpsLoc: () -> Unit,
val setManualLoc: (Double, Double) -> Unit,
val setQthLoc: (String) -> Unit
)
data class DataSettings(
val getUpdating: Boolean,
val getLastUpdated: Long,
val getSatellites: Int,
val getRadios: Int,
val isUpdating: Boolean,
val lastUpdated: Long,
val satsTotal: Int,
val radiosTotal: Int,
val updateFromWeb: () -> Unit,
val updateFromFile: (String) -> Unit,
val clearAllData: () -> Unit
@@ -25,6 +25,7 @@ import com.rtbishop.look4sat.domain.ILocationSource
import com.rtbishop.look4sat.domain.ISettingsSource
import com.rtbishop.look4sat.model.DataState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -37,11 +38,8 @@ class SettingsViewModel @Inject constructor(
) : ViewModel() {
private val defaultLocationSettings = LocationSettings(false,
locationSource.stationPosition.value.timestamp,
locationSource.stationPosition.value.latitude,
locationSource.stationPosition.value.longitude,
locationSource.stationPosition.value.qthLocator,
{ locationSource.setGpsPosition() },
locationSource.stationPosition.value,
{ updateStationPosition() },
{ lat, lon -> locationSource.setGeoPosition(lat, lon) },
{ locationSource.setQthPosition(it) })
val locationSettings = mutableStateOf(defaultLocationSettings)
@@ -66,22 +64,34 @@ class SettingsViewModel @Inject constructor(
val otherSettings = mutableStateOf(defaultOtherSettings)
init {
viewModelScope.launch {
locationSource.stationPosition.collect { stationPos ->
delay(125)
locationSettings.value = locationSettings.value.copy(
isUpdating = false, stationPos = stationPos
)
}
}
viewModelScope.launch {
repository.updateState.collect {
val isUpdating = it is DataState.Loading
dataSettings.value = dataSettings.value.copy(
getUpdating = isUpdating, getLastUpdated = settings.getLastUpdateTime()
isUpdating = isUpdating, lastUpdated = settings.getLastUpdateTime()
)
}
}
viewModelScope.launch {
combine(repository.getEntriesTotal(), repository.getRadiosTotal()) { sats, radios ->
dataSettings.value =
dataSettings.value.copy(getSatellites = sats, getRadios = radios)
dataSettings.value = dataSettings.value.copy(satsTotal = sats, radiosTotal = radios)
}.collect {}
}
}
private fun updateStationPosition() {
val isSuccessful = locationSource.setGpsPosition()
locationSettings.value = locationSettings.value.copy(isUpdating = isSuccessful)
}
private fun setUtc(value: Boolean) {
settings.setUtcState(value)
otherSettings.value = otherSettings.value.copy(getUtc = value)
+4 -5
View File
@@ -158,11 +158,10 @@
<string name="BTremote_output_hint">Формат данных</string>
<string name="BTremote_perm_error">Нет разрешения использовать bluetooth</string>
<string name="other_title">Другие настройки</string>
<string name="other_switch_utc">Показывать время по UTC</string>
<string name="other_switch_update">Обновлять данные автоматически</string>
<string name="other_switch_sweep">Показывать анимацию радара</string>
<string name="other_switch_sensors">Использовать сенсоры устройства</string>
<string name="other_switch_utc">• Показывать время по UTC</string>
<string name="other_switch_update">• Обновлять данные автоматически</string>
<string name="other_switch_sweep">• Показывать анимацию радара</string>
<string name="other_switch_sensors">• Использовать сенсоры устройства</string>
<string name="outro_title">Я хотел бы сказать спасибо:</string>
<string name="outro_thanks">• Вам за использование этого приложения! \nЖелаю всегда чистого неба над головой!
+4 -5
View File
@@ -158,11 +158,10 @@
<string name="BTremote_output_hint">数据格式</string>
<string name="BTremote_perm_error">请检查蓝牙权限</string>
<string name="other_title">其他偏好</string>
<string name="other_switch_utc">以 UTC 时间显示</string>
<string name="other_switch_update">启用卫星数据自动更新</string>
<string name="other_switch_sweep">启用雷达扫描动画</string>
<string name="other_switch_sensors">使用传感器旋转雷达视图</string>
<string name="other_switch_utc">• 以 UTC 时间显示</string>
<string name="other_switch_update">• 启用卫星数据自动更新</string>
<string name="other_switch_sweep">• 启用雷达扫描动画</string>
<string name="other_switch_sensors">• 使用传感器旋转雷达视图</string>
<string name="outro_title">我要感谢:</string>
<string name="outro_thanks">• 感谢下载和使用 Look4Sat!愿你的天空永远晴朗!
+13 -13
View File
@@ -147,6 +147,8 @@
<string name="data_success">Update completed successfully</string>
<string name="data_clear_success">Data was cleared successfully</string>
<string name="last_updated_pattern" translatable="false">d MMM yyyy - HH:mm:ss</string>
<string name="remote_title">Rotator preferences</string>
<string name="remote_switch">Enable remote control</string>
<string name="remote_ip_hint">IP address</string>
@@ -158,24 +160,22 @@
<string name="BTremote_output_hint">Data format</string>
<string name="BTremote_perm_error">Check your bluetooth permission</string>
<string name="other_title">Other preferences</string>
<string name="other_switch_utc">Show pass time in UTC</string>
<string name="other_switch_update">Enable automatic data update</string>
<string name="other_switch_sweep">Enable radar sweep animation</string>
<string name="other_switch_sensors">Use sensors to rotate radar view</string>
<string name="other_switch_utc">• Show pass time in UTC</string>
<string name="other_switch_update">• Enable automatic data update</string>
<string name="other_switch_sweep">• Enable radar sweep animation</string>
<string name="other_switch_sensors">• Use sensors to rotate radar view</string>
<string name="outro_title">I would like to say thanks to:</string>
<string name="outro_thanks">• You for downloading and using Look4Sat! \nMay your sky always be clear!
\n\n• <a href="https://github.com/g4dpz">David A. B. Johnson</a>
and <a href="https://github.com/davidmoten">Dave Moten</a> for creating predict4java lib
under the <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a>.
\n\n• <a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict
satellite tracker that inspired the creation of Look4Sat.
\n\n• <a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his
\n• <a href="https://github.com/g4dpz">David A. B. Johnson</a>
and <a href="https://github.com/davidmoten">Dave Moten</a> for creating a super useful predict4java library.
\n• <a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict
tracker that inspired the creation of Look4Sat.
\n• <a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his
<a href="https://celestrak.com/">Celestrak</a> website that provides access to the TLE data.
\n\n• <a href="https://libre.space/">Libre Space Foundation</a> for their
\n• <a href="https://libre.space/">Libre Space Foundation</a> for their
<a href="https://db.satnogs.org/">SatNOGS</a> API and DB providing a huge amount of data.
\n\n• <a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a>
\n• <a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a>
team for their interest to the app and the interview published.
</string>
<string name="outro_license">The app comes with no warranty.</string>