mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-04 11:37:22 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbf2229774 | ||
|
|
f2fc1b7b28 | ||
|
|
d600836e19 | ||
|
|
94bffe80b0 | ||
|
|
4260fbb096 |
No files matched your search
@@ -248,10 +248,15 @@ fun MainScreen(
|
|||||||
mapFilterViewModel = mapFilterViewModel,
|
mapFilterViewModel = mapFilterViewModel,
|
||||||
onMatchGrid = { grid ->
|
onMatchGrid = { grid ->
|
||||||
// Grid-QSO dialog "Match" button: pre-fill the
|
// Grid-QSO dialog "Match" button: pre-fill the
|
||||||
// match page for that grid and switch to its tab.
|
// match page for that grid and open it.
|
||||||
mutualViewModel.prefillMatchFromGrid(grid)
|
mutualViewModel.prefillMatchFromGrid(grid)
|
||||||
while (backStack.size > 1) backStack.removeAt(backStack.size - 1)
|
// Push Mutual on top of the Map entry instead of
|
||||||
backStack.add(Screen.Mutual)
|
// replacing the stack (bottom-nav style): the
|
||||||
|
// system back gesture then pops back to the map
|
||||||
|
// page, which is the page the user came from.
|
||||||
|
if (backStack.lastOrNull() !is Screen.Mutual) {
|
||||||
|
backStack.add(Screen.Mutual)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,6 @@ dependencies {
|
|||||||
testImplementation(libs.robolectric)
|
testImplementation(libs.robolectric)
|
||||||
testImplementation(libs.androidx.test.core)
|
testImplementation(libs.androidx.test.core)
|
||||||
testImplementation(libs.compose.ui.test.junit4)
|
testImplementation(libs.compose.ui.test.junit4)
|
||||||
|
testImplementation(libs.compose.navigation3)
|
||||||
debugImplementation(libs.compose.debug.manifest)
|
debugImplementation(libs.compose.debug.manifest)
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,13 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableFloatStateOf
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -220,8 +222,18 @@ private fun MutualContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set once the list has actually been laid out. The prefill scroll only
|
||||||
|
// fires after this, because on a real device the Mutual entry appears
|
||||||
|
// through the NavDisplay transition and LaunchedEffect alone can run
|
||||||
|
// before the list is measurable (the scroll then never lands and the
|
||||||
|
// page stays at the top). onGloballyPositioned fires on the first real
|
||||||
|
// layout, so the subsequent scrollToItem always has a measured list.
|
||||||
|
var listReady by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.onGloballyPositioned { listReady = true },
|
||||||
state = listState,
|
state = listState,
|
||||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
) {
|
) {
|
||||||
@@ -377,8 +389,8 @@ private fun MutualContent(
|
|||||||
// LazyListState at index 1: the constructor parameter is ignored by this
|
// LazyListState at index 1: the constructor parameter is ignored by this
|
||||||
// Compose version (verified in tests), while scrollToItem lands correctly.
|
// Compose version (verified in tests), while scrollToItem lands correctly.
|
||||||
val matchSearchIndex = if (state.errorMessage != null) 2 else 1
|
val matchSearchIndex = if (state.errorMessage != null) 2 else 1
|
||||||
LaunchedEffect(state.scrollToTimeRange, matchSearchIndex) {
|
LaunchedEffect(state.scrollToTimeRange, matchSearchIndex, listReady) {
|
||||||
if (state.scrollToTimeRange) {
|
if (state.scrollToTimeRange && listReady) {
|
||||||
listState.scrollToItem(matchSearchIndex)
|
listState.scrollToItem(matchSearchIndex)
|
||||||
viewModel.consumeScrollToTimeRange()
|
viewModel.consumeScrollToTimeRange()
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-3
@@ -12,6 +12,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.navigation3.runtime.entryProvider
|
||||||
|
import androidx.navigation3.runtime.rememberNavBackStack
|
||||||
|
import androidx.navigation3.ui.NavDisplay
|
||||||
|
import com.rtbishop.look4sat.core.presentation.Screen
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -38,7 +42,7 @@ import org.robolectric.annotation.GraphicsMode
|
|||||||
*/
|
*/
|
||||||
@RunWith(RobolectricTestRunner::class)
|
@RunWith(RobolectricTestRunner::class)
|
||||||
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
||||||
@Config(sdk = [34])
|
@Config(sdk = [34], qualifiers = "w411dp-h891dp-port")
|
||||||
class MutualMatchPrefillScrollTest {
|
class MutualMatchPrefillScrollTest {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
@@ -114,8 +118,7 @@ class MutualMatchPrefillScrollTest {
|
|||||||
fun prefillAutoStartsQueryAndFillsState() {
|
fun prefillAutoStartsQueryAndFillsState() {
|
||||||
val vm = MutualViewModel(FakeSatelliteRepo(), FakeSettingsRepo())
|
val vm = MutualViewModel(FakeSatelliteRepo(), FakeSettingsRepo())
|
||||||
vm.prefillMatchFromGrid("OL62")
|
vm.prefillMatchFromGrid("OL62")
|
||||||
val s = vm.uiState.value
|
val s = vm.uiState.value // Query auto-started: with the empty-satellite fake the query reaches
|
||||||
// Query auto-started: with the empty-satellite fake the query reaches
|
|
||||||
// the "no satellite data" guard (rather than never being triggered),
|
// the "no satellite data" guard (rather than never being triggered),
|
||||||
// proving prefillMatchFromGrid kicks off queryMutualPasses.
|
// proving prefillMatchFromGrid kicks off queryMutualPasses.
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@@ -127,4 +130,28 @@ class MutualMatchPrefillScrollTest {
|
|||||||
org.junit.Assert.assertEquals("OL62", s.stationBGrid)
|
org.junit.Assert.assertEquals("OL62", s.stationBGrid)
|
||||||
org.junit.Assert.assertEquals(24, s.hoursAhead)
|
org.junit.Assert.assertEquals(24, s.hoursAhead)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun navDisplayEntryAfterPrefill_scrollsToTimeRange() {
|
||||||
|
// Closest to the real device path: the Mutual screen composed inside a
|
||||||
|
// NavDisplay entry (back stack [Mutual]) right after prefillMatchFromGrid.
|
||||||
|
val vm = MutualViewModel(FakeSatelliteRepo(), FakeSettingsRepo())
|
||||||
|
vm.prefillMatchFromGrid("OL62")
|
||||||
|
composeRule.setContent {
|
||||||
|
val backStack = rememberNavBackStack(Screen.Mutual)
|
||||||
|
MaterialTheme {
|
||||||
|
Surface(modifier = Modifier.fillMaxSize()) {
|
||||||
|
NavDisplay(
|
||||||
|
backStack = backStack,
|
||||||
|
onBack = { backStack.removeLastOrNull() },
|
||||||
|
entryProvider = entryProvider {
|
||||||
|
entry<Screen.Mutual> { MutualScreen(viewModel = vm) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
composeRule.onNodeWithText("Time range").assertIsDisplayed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
[versions]
|
[versions]
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
appVersionCode = "488"
|
appVersionCode = "490"
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
appVersionName = "4.4.7-ba7opf.12.2"
|
appVersionName = "4.4.7-ba7opf.12.4"
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
compileSdk = "37"
|
compileSdk = "37"
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
|
|||||||
Reference in new issue
Block a user