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