Sleeping the device mid-video with "Ask for profile on app open" enabled left the app wedged on an unresponsive Choose Profile screen (Nvidia Shield). The picker is pushed on the root navigator, but the player's focus self-heal only consulted its own nested profile-session route, so it yanked D-pad focus back behind the picker whenever it lost it. Route currency now walks every enclosing navigator (isRouteChainCurrent) before the player reclaims focus, primes loading-phase navigation focus, or claims the surface on window focus. The resume-time prompt is also skipped entirely while a video player is active: waking mid-stream resumes the stream instead of stacking the picker over the session. close #2034
22 lines
930 B
Dart
22 lines
930 B
Dart
import 'package:flutter/widgets.dart';
|
|
|
|
/// Whether [context]'s enclosing route is the app's top visible route.
|
|
///
|
|
/// `ModalRoute.of(context).isCurrent` only answers for the route's own
|
|
/// navigator. With nested navigators that is not "nothing is on top": a route
|
|
/// pushed on an ancestor navigator — e.g. the root-navigator profile picker
|
|
/// over the nested profile-session navigator (#2034) — covers this route
|
|
/// while its own `isCurrent` stays true. Walks the hosting route of each
|
|
/// enclosing navigator up to the root, so any route stacked above [context]'s
|
|
/// route on any navigator makes this false.
|
|
bool isRouteChainCurrent(BuildContext context) {
|
|
ModalRoute<Object?>? route = ModalRoute.of(context);
|
|
while (route != null) {
|
|
if (!route.isCurrent) return false;
|
|
final navigator = route.navigator;
|
|
if (navigator == null) break;
|
|
route = ModalRoute.of(navigator.context);
|
|
}
|
|
return true;
|
|
}
|