Unverified Commit 0e521942 authored by chunhtai's avatar chunhtai Committed by GitHub
parent 6ec1ff23
......@@ -2927,6 +2927,10 @@ class _RouteEntry extends RouteTransitionRecord {
final _RestorationInformation? restorationInformation;
final bool pageBased;
/// The limit this route entry will attempt to pop in the case of route being
/// remove as a result of a page update.
static const int kDebugPopAttemptLimit = 100;
static final Route<dynamic> notAnnounced = _NotAnnounced();
_RouteLifecycle currentState;
......@@ -3268,6 +3272,20 @@ class _RouteEntry extends RouteTransitionRecord {
'This route cannot be marked for pop. Either a decision has already been '
'made or it does not require an explicit decision on how to transition out.',
);
// Remove state that prevents a pop, e.g. LocalHistoryEntry[s].
int attempt = 0;
while (route.willHandlePopInternally) {
assert(
() {
attempt += 1;
return attempt < kDebugPopAttemptLimit;
}(),
'Attempted to pop $route $kDebugPopAttemptLimit times, but still failed',
);
final bool popResult = route.didPop(result);
assert(!popResult);
}
pop<dynamic>(result);
_isWaitingForExitingDecision = false;
}
......
......@@ -1832,14 +1832,6 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
];
}
@override
bool get willHandlePopInternally {
final bool popEntriesCanPop = _popEntries.every((PopEntry popEntry) {
return popEntry.canPopNotifier.value;
});
return !popEntriesCanPop || super.willHandlePopInternally;
}
@override
String toString() => '${objectRuntimeType(this, 'ModalRoute')}($settings, animation: $_animation)';
}
......
......@@ -2910,6 +2910,90 @@ void main() {
);
});
testWidgets('Can pop route with local history entries using page api', (WidgetTester tester) async {
List<Page<void>> myPages = const <Page<void>>[
MaterialPage<void>(child: Text('page1')),
MaterialPage<void>(child: Text('page2')),
];
await tester.pumpWidget(
MediaQuery(
data: MediaQueryData.fromView(tester.view),
child: Localizations(
locale: const Locale('en', 'US'),
delegates: const <LocalizationsDelegate<dynamic>>[
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
child: Navigator(
pages: myPages,
onPopPage: (_, __) => false,
),
),
),
);
expect(find.text('page2'), findsOneWidget);
final ModalRoute<void> route = ModalRoute.of(tester.element(find.text('page2')))!;
bool entryRemoved = false;
route.addLocalHistoryEntry(LocalHistoryEntry(onRemove: () => entryRemoved = true));
expect(route.willHandlePopInternally, true);
myPages = const <Page<void>>[
MaterialPage<void>(child: Text('page1')),
];
await tester.pumpWidget(
MediaQuery(
data: MediaQueryData.fromView(tester.view),
child: Localizations(
locale: const Locale('en', 'US'),
delegates: const <LocalizationsDelegate<dynamic>>[
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
child: Navigator(
pages: myPages,
onPopPage: (_, __) => false,
),
),
),
);
expect(find.text('page1'), findsOneWidget);
expect(entryRemoved, isTrue);
});
testWidgets('ModalRoute must comply with willHandlePopInternally when there is a PopScope', (WidgetTester tester) async {
const List<Page<void>> myPages = <Page<void>>[
MaterialPage<void>(child: Text('page1')),
MaterialPage<void>(
child: PopScope(
canPop: false,
child: Text('page2'),
),
),
];
await tester.pumpWidget(
MediaQuery(
data: MediaQueryData.fromView(tester.view),
child: Localizations(
locale: const Locale('en', 'US'),
delegates: const <LocalizationsDelegate<dynamic>>[
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
child: Navigator(
pages: myPages,
onPopPage: (_, __) => false,
),
),
),
);
final ModalRoute<void> route = ModalRoute.of(tester.element(find.text('page2')))!;
// PopScope only prevents user trigger action, e.g. Navigator.maybePop.
// The page can still be popped by the system if it needs to.
expect(route.willHandlePopInternally, false);
expect(route.didPop(null), true);
});
testWidgets('can push and pop pages using page api', (WidgetTester tester) async {
late Animation<double> secondaryAnimationOfRouteOne;
late Animation<double> primaryAnimationOfRouteOne;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment