mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Implemented EclipsedIndicator and MapScroll on select
This commit is contained in:
1 parent
fdbdc513f1
commit
01139f76e7
6 files changed
+147
-100
No files matched your search
@@ -20,6 +20,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -82,19 +83,20 @@ fun NavGraphBuilder.mapDestination() {
|
||||
composable(Screen.Map.route) {
|
||||
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
|
||||
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
|
||||
MapScreen(uiState)
|
||||
val mapView = rememberMapViewWithLifecycle()
|
||||
MapScreen(uiState, mapView)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MapScreen(uiState: State<MapState>) {
|
||||
private fun MapScreen(uiState: State<MapState>, mapView: MapView) {
|
||||
val onItemClick = { item: OrbitalObject -> uiState.value.sendAction(MapAction.SelectItem(item)) }
|
||||
val selectPrev = { uiState.value.sendAction(MapAction.SelectPrev) }
|
||||
val selectNext = { uiState.value.sendAction(MapAction.SelectNext) }
|
||||
val rotateMod = Modifier.rotate(180f)
|
||||
val timeString = uiState.value.mapData?.aosTime ?: "00:00:00"
|
||||
val isTimeAos = uiState.value.mapData?.isTimeAos ?: true
|
||||
val osmInfo = "Wikimedia maps | Map data © OpenStreetMap contributors"
|
||||
val osmInfo = "© OpenStreetMap contributors"
|
||||
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
TimerRow {
|
||||
CardIcon(onClick = selectPrev, iconId = R.drawable.ic_arrow, modifier = rotateMod)
|
||||
@@ -104,7 +106,12 @@ private fun MapScreen(uiState: State<MapState>) {
|
||||
NextPassRow(pass = uiState.value.orbitalPass)
|
||||
ElevatedCard(modifier = Modifier.weight(1f)) {
|
||||
Box(contentAlignment = Alignment.BottomCenter) {
|
||||
MapView(isLightUi = uiState.value.isLightUi) { mapView ->
|
||||
LaunchedEffect(uiState.value.track) {
|
||||
val latitude = uiState.value.track?.get(0)?.get(0)?.latitude ?: 0.0
|
||||
val longitude = uiState.value.track?.get(0)?.get(0)?.longitude ?: 0.0
|
||||
mapView.controller.animateTo(GeoPoint(latitude, longitude))
|
||||
}
|
||||
AndroidView({ mapView }) { mapView ->
|
||||
uiState.value.stationPosition?.let { setStationPosition(it, mapView) }
|
||||
uiState.value.positions?.let { setPositions(it, mapView, onItemClick) }
|
||||
uiState.value.track?.let { setSatelliteTrack(it, mapView) }
|
||||
@@ -207,7 +214,6 @@ 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 ->
|
||||
@@ -222,7 +228,6 @@ private fun setSatelliteTrack(satTrack: List<List<GeoPos>>, mapView: MapView) {
|
||||
} catch (exception: Exception) {
|
||||
println(exception)
|
||||
}
|
||||
// mapView.controller.animateTo(center)
|
||||
}
|
||||
|
||||
private fun setFootprint(orbitalPos: OrbitalPos, mapView: MapView) {
|
||||
@@ -239,17 +244,7 @@ private fun setFootprint(orbitalPos: OrbitalPos, mapView: MapView) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MapView(
|
||||
modifier: Modifier = Modifier,
|
||||
isLightUi: Boolean,
|
||||
update: ((map: MapView) -> Unit)? = null
|
||||
) {
|
||||
val mapView = rememberMapViewWithLifecycle(isLightUi)
|
||||
AndroidView({ mapView }, modifier) { update?.invoke(it) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberMapViewWithLifecycle(isLightTheme: Boolean): MapView {
|
||||
private fun rememberMapViewWithLifecycle(): MapView {
|
||||
val tileSource = XYTileSource("tiles", 0, 6, 256, ".webp", emptyArray<String>())
|
||||
val context = LocalContext.current
|
||||
val mapView = remember { MapView(context) }.apply {
|
||||
@@ -263,7 +258,7 @@ private fun rememberMapViewWithLifecycle(isLightTheme: Boolean): MapView {
|
||||
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
|
||||
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
|
||||
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
|
||||
overlayManager.tilesOverlay.setColorFilter(getColorFilter(isLightTheme))
|
||||
overlayManager.tilesOverlay.setColorFilter(getColorFilter())
|
||||
setScrollableAreaLimitLatitude(maxLat, minLat, 0)
|
||||
// add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons
|
||||
overlays.addAll(Array(4) { FolderOverlay() })
|
||||
@@ -290,13 +285,13 @@ private fun rememberMapViewLifecycleObserver(mapView: MapView) = remember(mapVie
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getColorFilter(isLightTheme: Boolean): ColorMatrixColorFilter {
|
||||
private fun getColorFilter(): ColorMatrixColorFilter {
|
||||
val grayScale = ColorMatrix().apply { setSaturation(0f) }
|
||||
val negative = ColorMatrix(
|
||||
floatArrayOf(-1f, 0f, 0f, 0f, 260f, 0f, -1f, 0f, 0f, 260f, 0f, 0f, -1f, 0f, 260f, 0f, 0f, 0f, 1f, 0f)
|
||||
)
|
||||
negative.preConcat(grayScale)
|
||||
return if (isLightTheme) ColorMatrixColorFilter(grayScale) else ColorMatrixColorFilter(negative)
|
||||
return ColorMatrixColorFilter(negative)
|
||||
}
|
||||
|
||||
private fun getMinZoom(screenHeight: Int): Double {
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
@@ -60,7 +61,7 @@ fun NavGraphBuilder.passesDestination(navigateToRadar: (Int, Long) -> Unit) {
|
||||
modelClass = PassesViewModel::class.java,
|
||||
factory = PassesViewModel.Factory
|
||||
)
|
||||
val uiState = viewModel.uiState.value
|
||||
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
|
||||
PassesScreen(uiState, navigateToRadar)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.passes
|
||||
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -34,6 +32,9 @@ import com.rtbishop.look4sat.presentation.components.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.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -41,7 +42,7 @@ class PassesViewModel(
|
||||
private val satelliteRepo: ISatelliteRepo, private val settingsRepo: ISettingsRepo
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = mutableStateOf(
|
||||
private val _uiState = MutableStateFlow(
|
||||
PassesState(
|
||||
isPassesDialogShown = false,
|
||||
isRadiosDialogShown = false,
|
||||
@@ -58,7 +59,7 @@ class PassesViewModel(
|
||||
)
|
||||
)
|
||||
private var processing: Job? = null
|
||||
val uiState: State<PassesState> = _uiState
|
||||
val uiState: StateFlow<PassesState> = _uiState
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
@@ -69,7 +70,7 @@ class PassesViewModel(
|
||||
val timeNow = System.currentTimeMillis()
|
||||
val newPasses = satelliteRepo.processPasses(passes, timeNow)
|
||||
setPassInfo(newPasses, timeNow)
|
||||
_uiState.value = _uiState.value.copy(isRefreshing = false, itemsList = newPasses)
|
||||
_uiState.update { it.copy(isRefreshing = false, itemsList = newPasses) }
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
@@ -88,15 +89,15 @@ class PassesViewModel(
|
||||
}
|
||||
|
||||
private fun applyFilter(hoursAhead: Int, minElevation: Double, modes: List<String>) = viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isRefreshing = true)
|
||||
_uiState.update { it.copy(isRefreshing = true) }
|
||||
processing?.cancelAndJoin()
|
||||
settingsRepo.setPassesSettings(PassesSettings(hoursAhead, minElevation, modes))
|
||||
_uiState.value = _uiState.value.copy(hours = hoursAhead, elevation = minElevation, modes = modes)
|
||||
_uiState.update { it.copy(hours = hoursAhead, elevation = minElevation, modes = modes) }
|
||||
satelliteRepo.calculatePasses(System.currentTimeMillis(), hoursAhead, minElevation, modes)
|
||||
}
|
||||
|
||||
private fun refreshPasses() = viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isRefreshing = true)
|
||||
_uiState.update { it.copy(isRefreshing = true) }
|
||||
processing?.cancelAndJoin()
|
||||
val (hoursAhead, minElevation, modes) = settingsRepo.passesSettings.value
|
||||
satelliteRepo.calculatePasses(System.currentTimeMillis(), hoursAhead, minElevation, modes)
|
||||
@@ -107,22 +108,22 @@ class PassesViewModel(
|
||||
try {
|
||||
val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 }
|
||||
val time = nextPass.aosTime.minus(timeNow).toTimerString()
|
||||
_uiState.value = _uiState.value.copy(nextPass = nextPass, nextTime = time, isNextTimeAos = true)
|
||||
_uiState.update { it.copy(nextPass = nextPass, nextTime = time, isNextTimeAos = true) }
|
||||
} catch (exception: NoSuchElementException) {
|
||||
val lastPass = passes.last()
|
||||
val time = lastPass.losTime.minus(timeNow).toTimerString()
|
||||
_uiState.value = _uiState.value.copy(nextPass = lastPass, nextTime = time, isNextTimeAos = false)
|
||||
_uiState.update { it.copy(nextPass = lastPass, nextTime = time, isNextTimeAos = false) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFilterDialog() {
|
||||
val currentDialogState = _uiState.value.isPassesDialogShown
|
||||
_uiState.value = _uiState.value.copy(isPassesDialogShown = currentDialogState.not())
|
||||
_uiState.update { it.copy(isPassesDialogShown = currentDialogState.not()) }
|
||||
}
|
||||
|
||||
private fun toggleRadiosDialog() {
|
||||
val currentDialogState = _uiState.value.isRadiosDialogShown
|
||||
_uiState.value = _uiState.value.copy(isRadiosDialogShown = currentDialogState.not())
|
||||
_uiState.update { it.copy(isRadiosDialogShown = currentDialogState.not()) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -15,10 +15,13 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
@@ -101,7 +104,8 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 6.dp, vertical = 4.dp)
|
||||
) {
|
||||
Row(
|
||||
@@ -135,34 +139,35 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
|
||||
)
|
||||
}
|
||||
}
|
||||
if (uiState.orbitalPos.eclipsed) {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val textAlpha = infiniteTransition.animateFloat(
|
||||
initialValue = 1.0f,
|
||||
targetValue = 0.0f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = 500,
|
||||
delayMillis = 25,
|
||||
easing = LinearEasing
|
||||
),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
))
|
||||
Text(
|
||||
text = "Eclipsed!",
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.alpha(textAlpha.value)
|
||||
.border(2.dp, MaterialTheme.colorScheme.primary, MaterialTheme.shapes.medium)
|
||||
.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||
TransmittersList(transmitters = uiState.transmitters)
|
||||
if (uiState.transmitters.isEmpty()) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_satellite),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(64.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "This satellite doesn't have any known transcievers...",
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
TransmittersList(transmitters = uiState.transmitters)
|
||||
if (uiState.orbitalPos?.eclipsed == true) {
|
||||
EclipsedIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,6 +212,42 @@ private fun TransmitterItemPreview() {
|
||||
MainTheme { TransmitterItem(transmitter) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EclipsedIndicator() {
|
||||
val bgColor = MaterialTheme.colorScheme.primary
|
||||
val bgShape = MaterialTheme.shapes.medium
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val textAlpha = infiniteTransition.animateFloat(
|
||||
initialValue = 1.0f,
|
||||
targetValue = 0.0f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = 1000,
|
||||
delayMillis = 25,
|
||||
easing = LinearEasing
|
||||
),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.alpha(textAlpha.value)
|
||||
.border(width = 2.dp, color = bgColor, shape = bgShape),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = "Eclipsed!",
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
modifier = Modifier
|
||||
.background(color = bgColor, shape = bgShape)
|
||||
.padding(12.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TransmitterItem(radio: SatRadio) {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
@@ -224,7 +265,9 @@ private fun TransmitterItem(radio: SatRadio) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_arrow),
|
||||
tint = Color.Green,
|
||||
contentDescription = null, modifier = Modifier.rotate(90f).weight(0.15f)
|
||||
contentDescription = null, modifier = Modifier
|
||||
.rotate(90f)
|
||||
.weight(0.15f)
|
||||
)
|
||||
Text(
|
||||
text = if (radio.isInverted) "INVERTED: ${radio.info} " else "${radio.info} ",
|
||||
@@ -239,7 +282,9 @@ private fun TransmitterItem(radio: SatRadio) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_arrow),
|
||||
tint = Color.Red,
|
||||
contentDescription = null, modifier = Modifier.rotate(-90f).weight(0.15f)
|
||||
contentDescription = null, modifier = Modifier
|
||||
.rotate(-90f)
|
||||
.weight(0.15f)
|
||||
)
|
||||
}
|
||||
FrequencyRow(satRadio = radio)
|
||||
|
||||
@@ -32,6 +32,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
@@ -43,6 +44,7 @@ import com.rtbishop.look4sat.presentation.Screen
|
||||
import com.rtbishop.look4sat.presentation.components.CardButton
|
||||
import com.rtbishop.look4sat.presentation.components.gotoUrl
|
||||
import com.rtbishop.look4sat.presentation.components.showToast
|
||||
import org.osmdroid.library.BuildConfig
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
@@ -88,7 +90,7 @@ private fun SettingsScreen() {
|
||||
}
|
||||
|
||||
// Position settings
|
||||
val positionSettings = viewModel.positionSettings.value
|
||||
val positionSettings = viewModel.positionSettings.collectAsStateWithLifecycle().value
|
||||
val stationPos = positionSettings.stationPos
|
||||
val setGpsPos = { locationRequest.launch(arrayOf(locationPermCoarse, locationPermFine)) }
|
||||
val setGeoPos = { lat: Double, lon: Double -> viewModel.setGeoPosition(lat, lon) }
|
||||
@@ -106,13 +108,13 @@ private fun SettingsScreen() {
|
||||
}
|
||||
|
||||
// Data settings
|
||||
val dataSettings = viewModel.dataSettings.value
|
||||
val dataSettings = viewModel.dataSettings.collectAsStateWithLifecycle().value
|
||||
val updateFromWeb: () -> Unit = { viewModel.updateFromWeb() }
|
||||
val updateFromFile = { contentRequest.launch("*/*") }
|
||||
val clearAllData: () -> Unit = { viewModel.clearAllData() }
|
||||
|
||||
// Other settings
|
||||
val otherSettings = viewModel.otherSettings.value
|
||||
val otherSettings = viewModel.otherSettings.collectAsStateWithLifecycle().value
|
||||
val toggleUtc = { value: Boolean -> viewModel.toggleUtc(value) }
|
||||
val toggleUpdate = { value: Boolean -> viewModel.toggleUpdate(value) }
|
||||
val toggleSweep = { value: Boolean -> viewModel.toggleSweep(value) }
|
||||
@@ -428,13 +430,15 @@ 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) })
|
||||
if (BuildConfig.DEBUG) {
|
||||
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) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-29
@@ -17,8 +17,6 @@
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.settings
|
||||
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -29,6 +27,9 @@ import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.domain.model.OtherSettings
|
||||
import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SettingsViewModel(
|
||||
@@ -36,89 +37,89 @@ class SettingsViewModel(
|
||||
) : ViewModel() {
|
||||
|
||||
private val defaultPosSettings = PositionSettings(false, settingsRepo.stationPosition.value, 0)
|
||||
private val _positionSettings = mutableStateOf(defaultPosSettings)
|
||||
val positionSettings: State<PositionSettings> = _positionSettings
|
||||
private val _positionSettings = MutableStateFlow(defaultPosSettings)
|
||||
val positionSettings: StateFlow<PositionSettings> = _positionSettings
|
||||
|
||||
private val defaultDataSettings = DataSettings(false, 0, 0, 0L)
|
||||
private val _dataSettings = mutableStateOf(defaultDataSettings)
|
||||
val dataSettings: State<DataSettings> = _dataSettings
|
||||
private val _dataSettings = MutableStateFlow(defaultDataSettings)
|
||||
val dataSettings: StateFlow<DataSettings> = _dataSettings
|
||||
|
||||
private val _otherSettings = mutableStateOf(settingsRepo.otherSettings.value)
|
||||
val otherSettings: State<OtherSettings> = _otherSettings
|
||||
private val _otherSettings = MutableStateFlow(settingsRepo.otherSettings.value)
|
||||
val otherSettings: StateFlow<OtherSettings> = _otherSettings
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
settingsRepo.stationPosition.collect { geoPos ->
|
||||
_positionSettings.value =
|
||||
_positionSettings.value.copy(isUpdating = false, stationPos = geoPos)
|
||||
_positionSettings.update { it.copy(isUpdating = false, stationPos = geoPos) }
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
settingsRepo.databaseState.collect { state ->
|
||||
_dataSettings.value = _dataSettings.value.copy(
|
||||
isUpdating = false,
|
||||
entriesTotal = state.numberOfSatellites,
|
||||
radiosTotal = state.numberOfRadios,
|
||||
timestamp = state.updateTimestamp
|
||||
)
|
||||
_dataSettings.update {
|
||||
it.copy(
|
||||
isUpdating = false,
|
||||
entriesTotal = state.numberOfSatellites,
|
||||
radiosTotal = state.numberOfRadios,
|
||||
timestamp = state.updateTimestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
settingsRepo.otherSettings.collect { _otherSettings.value = it }
|
||||
settingsRepo.otherSettings.collect { settings -> _otherSettings.update { settings } }
|
||||
}
|
||||
}
|
||||
|
||||
fun setGpsPosition() {
|
||||
if (settingsRepo.setStationPositionGps()) {
|
||||
val messageResId = R.string.location_success
|
||||
_positionSettings.value =
|
||||
_positionSettings.value.copy(isUpdating = true, messageResId = messageResId)
|
||||
_positionSettings.update { it.copy(isUpdating = true, messageResId = messageResId) }
|
||||
} else {
|
||||
val errorResId = R.string.location_gps_error
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = errorResId)
|
||||
_positionSettings.update { it.copy(messageResId = errorResId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun setGeoPosition(latitude: Double, longitude: Double) {
|
||||
if (settingsRepo.setStationPositionGeo(latitude, longitude, 0.0)) {
|
||||
val messageResId = R.string.location_success
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = messageResId)
|
||||
_positionSettings.update { it.copy(messageResId = messageResId) }
|
||||
} else {
|
||||
val errorResId = R.string.location_manual_error
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = errorResId)
|
||||
_positionSettings.update { it.copy(messageResId = errorResId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun setQthPosition(locator: String) {
|
||||
if (settingsRepo.setStationPositionQth(locator)) {
|
||||
val messageResId = R.string.location_success
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = messageResId)
|
||||
_positionSettings.update { it.copy(messageResId = messageResId) }
|
||||
} else {
|
||||
val errorResId = R.string.location_qth_error
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = errorResId)
|
||||
_positionSettings.update { it.copy(messageResId = errorResId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun dismissPosMessage() {
|
||||
_positionSettings.value = _positionSettings.value.copy(messageResId = 0)
|
||||
_positionSettings.update { it.copy(messageResId = 0) }
|
||||
}
|
||||
|
||||
fun updateFromWeb() = viewModelScope.launch {
|
||||
try {
|
||||
_dataSettings.value = _dataSettings.value.copy(isUpdating = true)
|
||||
_dataSettings.update { it.copy(isUpdating = true) }
|
||||
databaseRepo.updateFromRemote()
|
||||
} catch (exception: Exception) {
|
||||
_dataSettings.value = _dataSettings.value.copy(isUpdating = false)
|
||||
_dataSettings.update { it.copy(isUpdating = false) }
|
||||
println(exception)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFromFile(uri: String) = viewModelScope.launch {
|
||||
try {
|
||||
_dataSettings.value = _dataSettings.value.copy(isUpdating = true)
|
||||
_dataSettings.update { it.copy(isUpdating = true) }
|
||||
databaseRepo.updateFromFile(uri)
|
||||
} catch (exception: Exception) {
|
||||
_dataSettings.value = _dataSettings.value.copy(isUpdating = false)
|
||||
_dataSettings.update { it.copy(isUpdating = false) }
|
||||
println(exception)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user