Skip to content

Commit f5c7df1

Browse files
bmanderclaude
andauthored
Don't reframe the route on ordinary arrivals polls (#1895) (#1896)
In stop + route focus, onArrivalsLoaded re-emits the selected route's ShowRoute directive on every arrivals load with frameRoute derived only from preserveViewport. On an ordinary poll preserveViewport is false, so frameRoute was true — routing through RouteMapController.reframe -> host.frameRoute() and snapping the camera back to the whole route's extent, discarding whatever the rider had panned/zoomed to. Frame the selected route only when the load is the initial (restore/deep-link) focus establishment. On an ordinary poll refresh the ShowRoute re-emission now carries frameRoute=false, so reframe() is a no-op (direction unchanged, no focusTripId) and the camera stays put. The initial route selection still frames via selectStopRoute's default frameRoute=true. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2049fdb commit f5c7df1

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

onebusaway-android/src/main/java/org/onebusaway/android/ui/home/HomeViewModel.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ class HomeViewModel @Inject constructor(
297297
focusedTrips = trips
298298
presentedRoutes = trips.mapTo(linkedSetOf(), FocusedTrip::routeDirection)
299299
val preserveViewport = pendingMapFocus && preserveViewportForPendingMapFocus
300+
// Frame the selected route only when this load is the initial (restore/deep-link) focus
301+
// establishment; an ordinary arrivals poll must refresh the presentation without reframing the
302+
// camera to the whole route (#1895). A restore carrying a saved viewport already declines to frame.
303+
val frameSelectedRoute = pendingMapFocus && !preserveViewportForPendingMapFocus
300304
if (pendingMapFocus) {
301305
pendingMapFocus = false
302306
preserveViewportForPendingMapFocus = false
@@ -323,7 +327,7 @@ class HomeViewModel @Inject constructor(
323327
MapDirective.ShowRoute(
324328
it.target(focus.stop.id).toRequest(),
325329
stopScoped = true,
326-
frameRoute = !preserveViewport,
330+
frameRoute = frameSelectedRoute,
327331
)
328332
)
329333
}

onebusaway-android/src/test/java/org/onebusaway/android/ui/home/HomeViewModelTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,32 @@ class HomeViewModelTest {
291291
mapJob.cancel()
292292
}
293293

294+
@Test
295+
fun `an ordinary arrivals poll refreshes the selected route without reframing`() = runTest {
296+
val vm = viewModel()
297+
val map = MapDirectiveRecorder(vm)
298+
val mapJob = launch { map.collect() }
299+
advanceUntilIdle()
300+
vm.onStopFocused(FocusedStop("stop", "Main St", "100", 47.6, -122.3))
301+
advanceUntilIdle()
302+
vm.selectArrivalRoute(
303+
request = ShowRouteRequest("65", directionStopId = "stop", initialDirectionId = 0),
304+
shortName = "65",
305+
headsign = "Downtown",
306+
)
307+
advanceUntilIdle()
308+
// Selecting the route frames it once.
309+
assertEquals(true, map.routeCommands.single().frameRoute)
310+
map.sent.clear()
311+
312+
// A subsequent arrivals poll (no pending focus) re-shows the selected route but must not reframe.
313+
vm.onArrivalsLoaded(ObaStopElement("stop", 47.6, -122.3, "Main St", "100"), emptyList(), emptySet())
314+
advanceUntilIdle()
315+
316+
assertEquals(false, map.routeCommands.single().frameRoute)
317+
mapJob.cancel()
318+
}
319+
294320
@Test
295321
fun `drawer route selection and continuation remain subordinate to stop focus`() = runTest {
296322
val savedState = SavedStateHandle()

0 commit comments

Comments
 (0)