fix(roaming): clock ticker moves the header time; GPS mirrors station pos

Two bugs from the last release:

1. The header clock was frozen: Date() was only evaluated during recomposition, and with no state changes the time never moved. Added a 1s LaunchedEffect ticker that updates a now-state, so the date/time text re-renders and actually advances — matching the reference app, which refreshes the clock on every location callback.

2. GPS indicator: replaced the 10-minute freshness check with a direct 'has a real fix' check (timestamp > 0 and coords non-zero). The page mirrors the station position (站位) from the shared StateFlow, so the GPS dot is green whenever the station has a fix — GPS shows exactly what the station GPS says, nothing more.
This commit is contained in:
mckero committed 2026-08-03 12:48:17 +00:00
1 parent eae6304124
commit 31ae04329d
2 files changed
+21 -6

No files matched your search

@@ -39,8 +39,11 @@ import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -83,6 +86,16 @@ fun RoamingScreen() {
RoamingState.fromPosition(stationPos)
}
// Clock ticker: re-render date/time every second so the header clock
// actually moves (the reference app refreshes it on every location fix).
var now by remember { mutableLongStateOf(System.currentTimeMillis()) }
LaunchedEffect(Unit) {
while (true) {
now = System.currentTimeMillis()
kotlinx.coroutines.delay(1_000L)
}
}
ScreenColumn(
topBar = {
TopBar { Text(text = "漫游", fontSize = 20.sp, fontWeight = FontWeight.Bold) }
@@ -93,14 +106,14 @@ fun RoamingScreen() {
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(spacing.medium)
) {
InfoCard(state = state)
InfoCard(state = state, now = now)
GridCard(state = state, modifier = Modifier.weight(1f))
}
}
}
@Composable
private fun InfoCard(state: RoamingState) {
private fun InfoCard(state: RoamingState, now: Long) {
val colorScheme = MaterialTheme.colorScheme
Column(
modifier = Modifier
@@ -126,13 +139,13 @@ private fun InfoCard(state: RoamingState) {
)
Spacer(modifier = Modifier.weight(1f))
Text(
text = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(Date()),
text = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(Date(now)),
fontSize = 14.sp,
color = colorScheme.onSecondaryContainer
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date()),
text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(now)),
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = colorScheme.onSecondaryContainer
@@ -44,7 +44,9 @@ data class RoamingState(
val locator = positionToQth(pos.latitude, pos.longitude) ?: return RoamingState()
val square = qthToSquare(locator)
val squares = if (square != "----") qthNeighbors(square) else List(9) { "----" }
val fresh = pos.timestamp > 0L && System.currentTimeMillis() - pos.timestamp < 600_000L
// GPS is simply whatever the station position says — a real fix
// (non-zero, with timestamp) counts as enabled.
val hasFix = pos.timestamp > 0L && (pos.latitude != 0.0 || pos.longitude != 0.0)
return RoamingState(
latitude = pos.latitude,
longitude = pos.longitude,
@@ -52,7 +54,7 @@ data class RoamingState(
gridSquares = squares,
markerX = markerFraction(locator, isLat = false),
markerY = markerFraction(locator, isLat = true),
gpsEnabled = fresh
gpsEnabled = hasFix
)
}