fix(mutual/radar): bigger radar shortcut; no bounce-back on finished pass

- Pass card header: radar icon button enlarged to 48dp touch target with a
  24dp icon, spanning both header rows vertically (name/time + elevations);
  the pass info column narrows so the Opposite elevation shifts left.
- RadarDestination no longer auto-returns instantly when the mutual pass has
  already ended — the auto-return now only runs while the pass is actually in
  progress. Previously the collapsed-card radar shortcut appeared broken
  ('flash back to Mutual') whenever the computed pass had finished.
- Fakes: add the 4 last-sync bookkeeping members missed by the LoTW commit.
This commit is contained in:
atsunatsu committed 2026-09-16 16:53:46 +08:00
1 parent f3fdf61784
commit 0ce177cfbf
3 files changed
+64 -44

No files matched your search

@@ -567,50 +567,63 @@ private fun MutualPassCard(
.clickable(onClick = onClick)
) {
Column(modifier = Modifier.padding(12.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = pass.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.weight(1f)
)
Text(
text = "${timeFormat.format(Date(pass.startTime))} - ${timeFormat.format(Date(pass.endTime))}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
// Radar shortcut, visible even on the collapsed card: icon only,
// rightmost position so the pass info shifts left. The card's own
// click (expand) is not triggered by the IconButton's tap.
IconButton(onClick = onNavigateToRadar) {
// Header: pass info (name/time + elevations) on the left, and a
// larger radar shortcut on the right that spans both rows vertically.
// The pass info column narrows, so the "Opposite" elevation shifts
// left to make room for the taller button.
Row(verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = pass.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f)
)
Text(
text = "${timeFormat.format(Date(pass.startTime))} - ${timeFormat.format(Date(pass.endTime))}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(Modifier.height(4.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = stringResource(R.string.mutual_elevation_you, pass.maxElevationA.toInt()),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary
)
Text(
text = stringResource(R.string.mutual_elevation_opposite, pass.maxElevationB.toInt()),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.tertiary
)
}
}
// Radar shortcut, visible even on the collapsed card: a taller
// button spanning both header rows. The card's own click
// (expand) is not triggered by the IconButton's tap.
IconButton(
onClick = onNavigateToRadar,
modifier = Modifier.size(48.dp)
) {
Icon(
painter = painterResource(id = R.drawable.ic_radar),
contentDescription = stringResource(R.string.mutual_open_radar),
modifier = Modifier.size(18.dp)
modifier = Modifier.size(24.dp)
)
}
}
Spacer(Modifier.height(4.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = stringResource(R.string.mutual_elevation_you, pass.maxElevationA.toInt()),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary
)
Text(
text = stringResource(R.string.mutual_elevation_opposite, pass.maxElevationB.toInt()),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.tertiary
)
}
AnimatedVisibility(
visible = isExpanded,
@@ -116,4 +116,8 @@ class FakeSettingsRepo(initialPosition: GeoPos = GeoPos(23.13, 113.26)) : ISetti
override fun getRoamedGrids(): Set<String> = TODO()
override fun setRoamedGrids(grids: Set<String>) = TODO()
override fun updateLoTWSettings(settings: LoTWSettings) = TODO()
override fun getLastLotwSyncDate(): String = ""
override fun setLastLotwSyncDate(date: String) = Unit
override fun getLastLotwSyncCallsign(): String = ""
override fun setLastLotwSyncCallsign(callsign: String) = Unit
}
@@ -101,14 +101,17 @@ fun RadarDestination(navigateUp: () -> Unit) {
}
LaunchedEffect(mutualData.endTime) {
if (mutualData.endTime <= 0L) return@LaunchedEffect
while (true) {
val remainingMs = mutualData.endTime - System.currentTimeMillis()
if (remainingMs <= 0L) {
navigateUpAndClearMutual()
return@LaunchedEffect
}
// Auto-return only while the mutual pass is actually in progress. An
// already-finished pass must NOT bounce the radar page back instantly
// (that made the pass-card radar shortcut look broken: tapping it while
// the computed pass had ended returned to Mutual immediately).
var remainingMs = mutualData.endTime - System.currentTimeMillis()
if (remainingMs <= 0L) return@LaunchedEffect
while (remainingMs > 0L) {
delay(remainingMs.coerceAtMost(1000L))
remainingMs = mutualData.endTime - System.currentTimeMillis()
}
navigateUpAndClearMutual()
}
// Sync actual permission state on every recomposition so it survives screen re-entry
val hasPermission = ContextCompat.checkSelfPermission(