Skip to content

Commit 05b2801

Browse files
bmanderclaude
andauthored
Restore trip-change notification tap into the directions focus (#1939) (#1940)
PR #1872 embedded directions into the home map and retired the standalone TripPlanScreen, whose maybeRestoreFromIntent was the only consumer of the trip-plan monitor's "your trip changed" notification intent. With that gone, tapping the alert opened generic HOME instead of the changed trip: the intent still carried the request bundle (copyIntoBundleSimple), the updated itineraries (OTPConstants.ITINERARIES, JSON), and INTENT_SOURCE=NOTIFICATION, but nothing in HOME read them. Re-add the consumer in HomeActivity's launch-intent side-effect path, driving the Activity-scoped VMs instead of the retired screen's: guard on INTENT_SOURCE=NOTIFICATION, JSON-decode the itineraries, rehydrate the request via TripRequestBuilder.initFromBundleSimple, then enterDirections() + TripPlanViewModel.restoreFrom(...) to inject the precomputed itineraries as PlanResult.Success without re-planning. The existing directions render path (results sheet + map draw) reacts with no further changes; the producer side and restoreFrom were already intact. No re-restore guard is needed: the launch-intent channel submits each real intent exactly once (cold onCreate seed, warm onNewIntent), so a config change doesn't re-fire it. params=null (monitor not re-armed from the restore) matches pre-#1872 behavior. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f3bd405 commit 05b2801

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

onebusaway-android/src/main/java/org/onebusaway/android/ui/HomeActivity.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ import androidx.compose.ui.ExperimentalComposeUiApi
3030
import androidx.compose.ui.Modifier
3131
import androidx.compose.ui.semantics.semantics
3232
import androidx.compose.ui.semantics.testTagsAsResourceId
33+
import androidx.core.content.IntentCompat
3334
import androidx.navigation.compose.rememberNavController
3435
import dagger.hilt.android.AndroidEntryPoint
3536
import javax.inject.Inject
3637
import org.onebusaway.android.R
38+
import org.onebusaway.android.directions.model.toTripItineraries
39+
import org.onebusaway.android.directions.util.OTPConstants
40+
import org.onebusaway.android.directions.util.TripRequestBuilder
3741
import org.onebusaway.android.ui.arrivals.ArrivalsLoaded
3842
import org.onebusaway.android.map.MapParams
3943
import org.onebusaway.android.map.MapViewModel
@@ -55,6 +59,7 @@ import org.onebusaway.android.ui.home.HomeViewModel
5559
import org.onebusaway.android.ui.home.HomeNavHost
5660
import org.onebusaway.android.ui.home.HomeDestinationDeps
5761
import org.onebusaway.android.ui.tripplan.TripPlanViewModel
62+
import org.onebusaway.android.ui.tripplan.toGeocoded
5863
import org.onebusaway.android.ui.tripresults.TripResultsViewModel
5964
import org.onebusaway.android.ui.home.LaunchIntentChannel
6065
import org.onebusaway.android.ui.home.LaunchIntentEffect
@@ -213,11 +218,48 @@ class HomeActivity : AppCompatActivity() {
213218
*/
214219
private fun applyLaunchIntentSideEffects(intent: Intent) {
215220
applyIntentSideEffects(intent)
221+
maybeRestoreDirectionsFromIntent(intent)
216222
if (intent.extras?.getBoolean(TutorialPrefs.TUTORIAL_WELCOME) == true) {
217223
viewModel.requestWelcomeTutorial()
218224
}
219225
}
220226

227+
/**
228+
* Re-entry from a trip-plan monitor "your trip changed" notification (see
229+
* [org.onebusaway.android.directions.realtime.TripPlanMonitorService.notifyChange]): the intent
230+
* carries the simplified request bundle ([TripRequestBuilder.copyIntoBundleSimple]), the updated
231+
* itineraries JSON ([OTPConstants.ITINERARIES]), and [OTPConstants.INTENT_SOURCE] =
232+
* [OTPConstants.Source.NOTIFICATION]. Switch HOME into the directions focus and seed the form +
233+
* results from those extras — the itineraries are injected as-is (no re-plan). Restores the behavior
234+
* the retired standalone screen's `maybeRestoreFromIntent` used to provide (#1939).
235+
*
236+
* No re-restore guard is needed: the launch-intent channel submits each real intent exactly once
237+
* (cold `onCreate` seed gated on a null `savedInstanceState`, warm `onNewIntent`), so a config change
238+
* doesn't re-fire this — and the activity-scoped [tripPlanViewModel] keeps the restored results.
239+
*/
240+
// UnwrappedClockValue: the trip-plan time defaults to device "now" only when the intent carries none.
241+
@Suppress("UnwrappedClockValue")
242+
private fun maybeRestoreDirectionsFromIntent(intent: Intent) {
243+
val source = IntentCompat.getSerializableExtra(
244+
intent, OTPConstants.INTENT_SOURCE, OTPConstants.Source::class.java
245+
)
246+
if (source != OTPConstants.Source.NOTIFICATION) return
247+
248+
val itineraries = intent.getStringExtra(OTPConstants.ITINERARIES)?.toTripItineraries().orEmpty()
249+
if (itineraries.isEmpty()) return
250+
251+
val extras = intent.extras ?: return
252+
val builder = TripRequestBuilder.initFromBundleSimple(this, extras)
253+
viewModel.enterDirections()
254+
tripPlanViewModel.restoreFrom(
255+
from = builder.from?.toGeocoded(),
256+
to = builder.to?.toGeocoded(),
257+
dateTimeMillis = builder.dateTime?.toEpochMilli() ?: System.currentTimeMillis(),
258+
arriving = builder.arriveBy,
259+
itineraries = itineraries,
260+
)
261+
}
262+
221263
/**
222264
* Runs the domain mutations implied by certain incoming intents, kept out of [IntentRouteMapper]'s
223265
* pure route mapping so that stays a side-effect-free translator: the `add-region` deep link applies

0 commit comments

Comments
 (0)