diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 716952b6793a..1a9b112bfb11 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.0 + +- Adds `popUntil` method to `GoRouterDelegate`, `GoRouter` and `GoRouterHelper`. + ## 6.0.4 - Fixes redirection info log. diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 07bcdf0dbb4f..40dd94aa3af0 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -146,6 +146,17 @@ class GoRouterDelegate extends RouterDelegate return true; } + /// Calls [pop] repeatedly until the predicate returns `true`. + void popUntil(RoutePredicate predicate) { + final _NavigatorStateIterator iterator = _createNavigatorStateIterator(); + while (iterator.moveNext()) { + if (iterator.current.canPop()) { + iterator.current.popUntil(predicate); + return; + } + } + } + /// Replaces the top-most page of the page stack with the given one. /// /// See also: diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart index fe37e342fb1d..ee9be277e50a 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -59,8 +59,21 @@ extension GoRouterHelper on BuildContext { /// Pop the top page off the Navigator's page stack by calling /// [Navigator.pop]. + /// + /// See also: + /// * [popUntil] which calls [pop] repeatedly until the predicate returns + /// `true`. void pop([T? result]) => GoRouter.of(this).pop(result); + /// Calls [pop] repeatedly until the predicate returns true. + /// + /// See also: + /// + /// * [pop] which pops the top page off the Navigator's page stack by calling + /// [Navigator.pop]. + void popUntil(RoutePredicate predicate) => + GoRouter.of(this).popUntil(predicate); + /// Replaces the top-most page of the page stack with the given URL location /// w/ optional query parameters, e.g. `/family/f2/person/p1?color=blue`. /// diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index 73a86c645de6..0e29bd70f539 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -284,6 +284,11 @@ class GoRouter extends ChangeNotifier implements RouterConfig { _routerDelegate.pop(result); } + /// Calls [pop] repeatedly until the predicate returns true. + void popUntil(RoutePredicate predicate) { + _routerDelegate.popUntil(predicate); + } + /// Refresh the route. void refresh() { assert(() { diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index fcac2baace64..fcf13313f83c 100644 --- a/packages/go_router/pubspec.yaml +++ b/packages/go_router/pubspec.yaml @@ -1,7 +1,7 @@ name: go_router description: A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more -version: 6.0.4 +version: 6.1.0 repository: https://github.com/flutter/packages/tree/main/packages/go_router issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22 diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart index 62f4b691d988..14acd8dcb4c4 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -54,6 +54,27 @@ void main() { }); }); + group('popUntil', () { + testWidgets('It should pop 2 pages', (WidgetTester tester) async { + final GoRouter goRouter = await createGoRouter(tester) + ..push('/a') + ..push('/a'); + + await tester.pumpAndSettle(); + expect(goRouter.routerDelegate.matches.matches.length, 3); + goRouter.routerDelegate.addListener(expectAsync0(count: 2, () {})); + final RouteMatch second = goRouter.routerDelegate.matches.matches[1]; + final RouteMatch last = goRouter.routerDelegate.matches.matches.last; + + int count = 0; + goRouter.popUntil((Route routeMatch) => count++ >= 2); + + expect(goRouter.routerDelegate.matches.matches.length, 1); + expect(goRouter.routerDelegate.matches.matches.contains(second), false); + expect(goRouter.routerDelegate.matches.matches.contains(last), false); + }); + }); + group('push', () { testWidgets( 'It should return different pageKey when push is called',