From 0ce177cfbf62c76748d4c04adc322c7c6ed3f801 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Wed, 16 Sep 2026 16:53:46 +0800 Subject: [PATCH] fix(mutual/radar): bigger radar shortcut; no bounce-back on finished pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- .../look4sat/feature/mutual/MutualScreen.kt | 89 +++++++++++-------- .../rtbishop/look4sat/feature/mutual/Fakes.kt | 4 + .../look4sat/feature/radar/RadarScreen.kt | 15 ++-- 3 files changed, 64 insertions(+), 44 deletions(-) diff --git a/feature/mutual/src/main/java/com/rtbishop/look4sat/feature/mutual/MutualScreen.kt b/feature/mutual/src/main/java/com/rtbishop/look4sat/feature/mutual/MutualScreen.kt index 9cb3ffd1..f2e1ccc0 100644 --- a/feature/mutual/src/main/java/com/rtbishop/look4sat/feature/mutual/MutualScreen.kt +++ b/feature/mutual/src/main/java/com/rtbishop/look4sat/feature/mutual/MutualScreen.kt @@ -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, diff --git a/feature/mutual/src/test/java/com/rtbishop/look4sat/feature/mutual/Fakes.kt b/feature/mutual/src/test/java/com/rtbishop/look4sat/feature/mutual/Fakes.kt index ca481be9..3a4eb8d5 100644 --- a/feature/mutual/src/test/java/com/rtbishop/look4sat/feature/mutual/Fakes.kt +++ b/feature/mutual/src/test/java/com/rtbishop/look4sat/feature/mutual/Fakes.kt @@ -116,4 +116,8 @@ class FakeSettingsRepo(initialPosition: GeoPos = GeoPos(23.13, 113.26)) : ISetti override fun getRoamedGrids(): Set = TODO() override fun setRoamedGrids(grids: Set) = 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 } \ No newline at end of file diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt index b580c732..74164712 100644 --- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt +++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt @@ -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(