feat(map): run the Match query before navigating to the mutual page

Tapping the grid-QSO dialog "Match" button now starts the pass query on
the map page and only navigates to the match page once it finishes, so the
page's first frame already contains the results — the time-range card at
the top and the pass curves right below, with no scroll flicker. The dialog
button shows a spinner and is disabled while calculating. A uiState
collector in MainScreen performs the actual navigation (still a push, so
the back gesture returns to the map). Failures/exceptions still navigate so
the user is never stuck on the map page.
This commit is contained in:
atsunatsu committed 2026-09-22 16:41:55 +08:00
1 parent d6bdf5ecb6
commit 0e28231c4a
3 files changed
+58 -17

No files matched your search

@@ -54,6 +54,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -153,7 +154,10 @@ fun MapDestination(
mapFilterViewModel: MapFilterViewModel,
// Invoked with the tapped grid when the QSO dialog's "Match" button is
// pressed: navigate to the match page pre-filled for that grid.
onMatchGrid: (String) -> Unit = {}
onMatchGrid: (String) -> Unit = {},
// True while the map "Match" query is running (the page only navigates
// once the query finished, so the match page opens with results ready).
matchCalculating: Boolean = false
) {
val context = LocalContext.current
val container = (context.applicationContext as IContainerProvider).getMainContainer()
@@ -190,7 +194,7 @@ fun MapDestination(
viewModel.onAction(MapAction.SetVisible(false))
}
}
MapScreen(uiState, viewModel::onAction, mapView, mapFilterViewModel, onMatchGrid)
MapScreen(uiState, viewModel::onAction, mapView, mapFilterViewModel, onMatchGrid, matchCalculating)
}
@Composable
@@ -199,7 +203,8 @@ private fun MapScreen(
onAction: (MapAction) -> Unit,
mapView: MapView,
mapFilterViewModel: MapFilterViewModel,
onMatchGrid: (String) -> Unit
onMatchGrid: (String) -> Unit,
matchCalculating: Boolean
) {
val rotateMod = Modifier.rotate(180f)
val timeString = uiState.mapData?.aosTime ?: "00:00:00"
@@ -423,6 +428,7 @@ private fun MapScreen(
grid = grid,
qsos = uiState.workedGridQsos[grid].orEmpty().sortedBy { it.epochMs },
isUtc = uiState.isUtc,
matchCalculating = matchCalculating,
onDismiss = { selectedGrid = null },
onMatch = { onMatchGrid(grid) }
)
@@ -436,6 +442,7 @@ private fun WorkedGridQsoDialog(
grid: String,
qsos: List<com.rtbishop.look4sat.core.domain.model.GridQso>,
isUtc: Boolean,
matchCalculating: Boolean,
onDismiss: () -> Unit,
onMatch: () -> Unit
) {
@@ -467,16 +474,24 @@ private fun WorkedGridQsoDialog(
)
}
TextButton(
enabled = !matchCalculating,
onClick = {
onDismiss()
onMatch()
}
) {
Icon(
painter = painterResource(R.drawable.ic_radio_tower),
contentDescription = null,
modifier = Modifier.size(18.dp)
)
if (matchCalculating) {
CircularProgressIndicator(
modifier = Modifier.size(18.dp),
strokeWidth = 2.dp
)
} else {
Icon(
painter = painterResource(R.drawable.ic_radio_tower),
contentDescription = null,
modifier = Modifier.size(18.dp)
)
}
Spacer(Modifier.width(4.dp))
Text(stringResource(R.string.grid_qso_match))
}