Fixed UTC pass time problem mentioned in issue #201

This commit is contained in:
Arty Bishop committed 2026-04-05 11:27:27 +01:00
1 parent be96602c76
commit 6588291997
9 files changed
+57 -18

No files matched your search

@@ -45,6 +45,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -62,8 +63,7 @@ import com.rtbishop.look4sat.core.domain.predict.OrbitalPass
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
import java.util.TimeZone
@Composable
@Preview(showBackground = true)
@@ -118,7 +118,13 @@ private fun NextPassRowPreview() = MainTheme {
}
@Composable
fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier, isUtc: Boolean = false) {
val timeZone = remember(isUtc) {
if (isUtc) TimeZone.getTimeZone("UTC") else TimeZone.getDefault()
}
val sdfTime = remember(isUtc) {
SimpleDateFormat("HH:mm:ss", Locale.ENGLISH).also { it.timeZone = timeZone }
}
ElevatedCard(
modifier = modifier
.height(48.dp)
@@ -140,12 +140,12 @@ private fun MapScreen(uiState: MapState, mapView: MapView) {
TimerRow(timeString = timeString, isTimeAos = isTimeAos)
IconCard(action = selectNext, resId = R.drawable.ic_arrow)
}
TopBar { NextPassRow(pass = uiState.orbitalPass) }
TopBar { NextPassRow(pass = uiState.orbitalPass, isUtc = uiState.isUtc) }
} else {
TopBar {
IconCard(action = selectPrev, resId = R.drawable.ic_arrow, modifier = rotateMod)
TimerRow(timeString = timeString, isTimeAos = isTimeAos)
NextPassRow(pass = uiState.orbitalPass, modifier = Modifier.weight(1f))
NextPassRow(pass = uiState.orbitalPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc)
IconCard(action = selectNext, resId = R.drawable.ic_arrow)
}
}
@@ -25,6 +25,7 @@ import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
data class MapState(
val mapData: MapData?,
val isLightUi: Boolean,
val isUtc: Boolean,
val stationPosition: GeoPos?,
val orbitalPass: OrbitalPass,
val track: List<List<GeoPos>>?,
@@ -43,12 +43,13 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.util.Date
class MapViewModel(private val satelliteRepo: ISatelliteRepo, settingsRepo: ISettingsRepo) :
class MapViewModel(private val satelliteRepo: ISatelliteRepo, private val settingsRepo: ISettingsRepo) :
ViewModel() {
private val stationPos = settingsRepo.stationPosition.value
@@ -57,6 +58,7 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, settingsRepo: ISet
MapState(
mapData = null,
isLightUi = settingsRepo.otherSettings.value.stateOfLightTheme,
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
stationPosition = null,
orbitalPass = defaultPass,
track = null,
@@ -73,6 +75,11 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, settingsRepo: ISet
val uiState: StateFlow<MapState> = _uiState
init {
viewModelScope.launch {
settingsRepo.otherSettings.collectLatest { settings ->
_uiState.update { it.copy(isUtc = settings.stateOfUtc) }
}
}
selectDefaultSatellite(-1)
}
@@ -77,9 +77,7 @@ import com.rtbishop.look4sat.core.presentation.isVerticalLayout
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
private val sdfDate = SimpleDateFormat("EEE dd MMM", Locale.ENGLISH)
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
import java.util.TimeZone
fun NavGraphBuilder.passesDestination(navigateToRadar: (Int, Long) -> Unit) {
composable(Screen.Passes.route) {
@@ -131,7 +129,7 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U
TimerRow(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos)
},
bottomInfo = {
NextPassRow(pass = uiState.nextPass)
NextPassRow(pass = uiState.nextPass, isUtc = uiState.isUtc)
},
endAction = {
IconCard(action = showRadiosDialog, resId = R.drawable.ic_radios)
@@ -141,6 +139,7 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U
) { _ ->
PassesList(
isRefreshing = uiState.isRefreshing,
isUtc = uiState.isUtc,
passes = uiState.itemsList,
navigateToRadar = navigateToRadar,
refreshPasses = refreshList,
@@ -153,6 +152,7 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U
@Composable
private fun PassesList(
isRefreshing: Boolean,
isUtc: Boolean,
passes: List<OrbitalPass>,
navigateToRadar: (Int, Long) -> Unit,
refreshPasses: () -> Unit,
@@ -188,7 +188,8 @@ private fun PassesList(
pass = pass,
navigateToRadar = navigateToRadar,
modifier = Modifier.animateItem(),
isVerticalLayout = isVerticalLayout
isVerticalLayout = isVerticalLayout,
isUtc = isUtc
)
}
}
@@ -220,14 +221,24 @@ private fun NearEarthPass(
pass: OrbitalPass,
navigateToRadar: (Int, Long) -> Unit,
modifier: Modifier = Modifier,
isVerticalLayout: Boolean = true
isVerticalLayout: Boolean = true,
isUtc: Boolean = false
) {
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
val horizontalPadding = if (isVerticalLayout) 6.dp else 10.dp
val timeZone = remember(isUtc) {
if (isUtc) TimeZone.getTimeZone("UTC") else TimeZone.getDefault()
}
val sdfDate = remember(isUtc) {
SimpleDateFormat("EEE dd MMM", Locale.ENGLISH).also { it.timeZone = timeZone }
}
val sdfTime = remember(isUtc) {
SimpleDateFormat("HH:mm:ss", Locale.ENGLISH).also { it.timeZone = timeZone }
}
// Cache formatted date/time strings — aosTime/losTime never change for a given pass
val aosDateStr = remember(pass.aosTime) { sdfDate.format(Date(pass.aosTime)) }
val aosTimeStr = remember(pass.aosTime) { sdfTime.format(Date(pass.aosTime)) }
val losTimeStr = remember(pass.losTime) { sdfTime.format(Date(pass.losTime)) }
val aosDateStr = remember(pass.aosTime, isUtc) { sdfDate.format(Date(pass.aosTime)) }
val aosTimeStr = remember(pass.aosTime, isUtc) { sdfTime.format(Date(pass.aosTime)) }
val losTimeStr = remember(pass.losTime, isUtc) { sdfTime.format(Date(pass.losTime)) }
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
Surface(modifier = Modifier
.padding(bottom = 2.dp)
@@ -93,7 +93,12 @@ class PassesViewModel(
}
viewModelScope.launch {
settingsRepo.otherSettings.collectLatest { settings ->
_uiState.update { it.copy(shouldSeeWhatsNew = settings.shouldSeeWhatsNew) }
_uiState.update {
it.copy(
isUtc = settings.stateOfUtc,
shouldSeeWhatsNew = settings.shouldSeeWhatsNew
)
}
}
}
}
@@ -113,12 +113,12 @@ private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) {
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
}
TopBar { NextPassRow(pass = upcomingPass) }
TopBar { NextPassRow(pass = upcomingPass, isUtc = uiState.isUtc) }
} else {
TopBar {
IconCard(action = navigateUp, resId = R.drawable.ic_back)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f))
NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc)
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
}
}
@@ -25,6 +25,7 @@ data class RadarState(
val currentPass: OrbitalPass?,
val currentTime: String,
val isCurrentTimeAos: Boolean,
val isUtc: Boolean,
val orientationValues: Pair<Float, Float>,
val orbitalPos: OrbitalPos?,
val satTrack: List<OrbitalPos>,
@@ -39,6 +39,7 @@ import com.rtbishop.look4sat.core.domain.utility.toTimerString
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@@ -58,6 +59,7 @@ class RadarViewModel(
currentPass = null,
currentTime = "00:00:00",
isCurrentTimeAos = true,
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
orientationValues = sensorsRepo.orientation.value,
orbitalPos = null,
satTrack = emptyList(),
@@ -84,6 +86,12 @@ class RadarViewModel(
}
}
}
// React to UTC setting changes
viewModelScope.launch {
settingsRepo.otherSettings.collectLatest { settings ->
_uiState.update { it.copy(isUtc = settings.stateOfUtc) }
}
}
// Resolve which pass we're tracking
viewModelScope.launch {
val catNum = savedStateHandle.get<Int>("catNum") ?: 0