From 4a809f3384e51ec042211755a2bd5d5055d15371 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Sat, 22 Oct 2022 21:29:29 +0800 Subject: [PATCH 1/7] :sparkles: Add popUntil --- packages/go_router/lib/src/delegate.dart | 12 ++++++++++++ packages/go_router/lib/src/misc/extensions.dart | 5 +++++ packages/go_router/lib/src/router.dart | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 9bcfa04dd86..0b53c544689 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -146,6 +146,18 @@ class GoRouterDelegate extends RouterDelegate notifyListeners(); } + /// Calls [pop] repeatedly until the predicate returns true. + void popUntil(bool Function(RouteMatch) predicate) { + bool hasPopped = false; + while (!predicate(_matchList.last)) { + hasPopped = true; + _matchList.pop(); + } + if (hasPopped) { + notifyListeners(); + } + } + /// 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 65e45cba349..70c67572b12 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; +import '../match.dart'; import '../router.dart'; /// Dart extension to add navigation function to a BuildContext object, e.g. @@ -61,6 +62,10 @@ extension GoRouterHelper on BuildContext { /// [Navigator.pop]. void pop() => GoRouter.of(this).pop(); + /// Calls [pop] repeatedly until the predicate returns true. + void popUntil(bool Function(RouteMatch) 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 cc160883d60..e289a39adaf 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -8,6 +8,7 @@ import 'configuration.dart'; import 'delegate.dart'; import 'information_provider.dart'; import 'logging.dart'; +import 'match.dart'; import 'matching.dart'; import 'misc/inherited_router.dart'; import 'parser.dart'; @@ -259,6 +260,11 @@ class GoRouter extends ChangeNotifier _routerDelegate.pop(); } + /// Calls [pop] repeatedly until the predicate returns true. + void popUntil(bool Function(RouteMatch) predicate) { + _routerDelegate.popUntil(predicate); + } + /// Refresh the route. void refresh() { assert(() { From 0047433678cd6da0dbc3ede7ce1ab3322f5b9c58 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Sat, 22 Oct 2022 21:29:39 +0800 Subject: [PATCH 2/7] :white_check_mark: Test popUntil --- packages/go_router/test/delegate_test.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart index f60ce65fd95..8f5cb7614cf 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -56,6 +56,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(() {})); + final RouteMatch second = goRouter.routerDelegate.matches.matches[1]; + final RouteMatch last = goRouter.routerDelegate.matches.matches.last; + + int count = 0; + goRouter.popUntil((RouteMatch 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', From 419643192fa9652e97028853721f3b0f616a8de2 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Sat, 22 Oct 2022 21:36:03 +0800 Subject: [PATCH 3/7] :memo: Update the documentation --- packages/go_router/CHANGELOG.md | 3 ++- packages/go_router/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 4d326cd2dab..54b46106eb7 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,7 +1,8 @@ -## NEXT +## 5.2.0 - Update README - Removes dynamic calls in examples. +- Adds `popUntil` method to `GoRouterDelegate`, `GoRouter` and `GoRouterHelper`. ## 5.1.1 diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index f2c47050bf4..5655bd6d89d 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: 5.1.1 +version: 5.2.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 From f9e08c21d8ef986cef270330385df7f270b40322 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Fri, 16 Dec 2022 18:44:41 +0800 Subject: [PATCH 4/7] :recycle: Call pop repeatedly --- packages/go_router/lib/src/delegate.dart | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 1585db8207d..9c14c950107 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -141,15 +141,10 @@ class GoRouterDelegate extends RouterDelegate return true; } - /// Calls [pop] repeatedly until the predicate returns true. + /// Calls [pop] repeatedly until the predicate returns `true`. void popUntil(bool Function(RouteMatch) predicate) { - bool hasPopped = false; while (!predicate(_matchList.last)) { - hasPopped = true; - _matchList.pop(); - } - if (hasPopped) { - notifyListeners(); + pop(); } } From 51395cd5e5bf771bf98793ad535527b70fb40ecd Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Fri, 16 Dec 2022 18:45:19 +0800 Subject: [PATCH 5/7] :memo: Update the documentation --- packages/go_router/lib/src/misc/extensions.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart index 70c67572b12..cbdf3ed34f5 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -60,9 +60,18 @@ 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() => GoRouter.of(this).pop(); /// 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(bool Function(RouteMatch) predicate) => GoRouter.of(this).popUntil(predicate); From 43ec575a35b80586ccdd5dd9912620a1d43516d3 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Fri, 16 Dec 2022 18:45:36 +0800 Subject: [PATCH 6/7] :white_check_mark: Update the tests --- packages/go_router/test/delegate_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart index 0f91cea765c..33fa7837cf8 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -62,7 +62,7 @@ void main() { await tester.pumpAndSettle(); expect(goRouter.routerDelegate.matches.matches.length, 3); - goRouter.routerDelegate.addListener(expectAsync0(() {})); + goRouter.routerDelegate.addListener(expectAsync0(count: 2, () {})); final RouteMatch second = goRouter.routerDelegate.matches.matches[1]; final RouteMatch last = goRouter.routerDelegate.matches.matches.last; From 2c48f397224c395df82d897eade32ee8077ba101 Mon Sep 17 00:00:00 2001 From: ValentinVignal Date: Tue, 7 Feb 2023 17:46:06 +0800 Subject: [PATCH 7/7] :alembic: Use navigator pop until --- packages/go_router/lib/src/delegate.dart | 10 +++++++--- packages/go_router/lib/src/misc/extensions.dart | 3 +-- packages/go_router/lib/src/router.dart | 3 +-- packages/go_router/test/delegate_test.dart | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index dc316d7e8ea..40dd94aa3af 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -147,9 +147,13 @@ class GoRouterDelegate extends RouterDelegate } /// Calls [pop] repeatedly until the predicate returns `true`. - void popUntil(bool Function(RouteMatch) predicate) { - while (!predicate(_matchList.last)) { - pop(); + void popUntil(RoutePredicate predicate) { + final _NavigatorStateIterator iterator = _createNavigatorStateIterator(); + while (iterator.moveNext()) { + if (iterator.current.canPop()) { + iterator.current.popUntil(predicate); + return; + } } } diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart index 392e227a850..ee9be277e50 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -4,7 +4,6 @@ import 'package:flutter/widgets.dart'; -import '../match.dart'; import '../router.dart'; /// Dart extension to add navigation function to a BuildContext object, e.g. @@ -72,7 +71,7 @@ extension GoRouterHelper on BuildContext { /// /// * [pop] which pops the top page off the Navigator's page stack by calling /// [Navigator.pop]. - void popUntil(bool Function(RouteMatch) predicate) => + void popUntil(RoutePredicate predicate) => GoRouter.of(this).popUntil(predicate); /// Replaces the top-most page of the page stack with the given URL location diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index 488180b148c..0e29bd70f53 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -8,7 +8,6 @@ import 'configuration.dart'; import 'delegate.dart'; import 'information_provider.dart'; import 'logging.dart'; -import 'match.dart'; import 'matching.dart'; import 'misc/inherited_router.dart'; import 'parser.dart'; @@ -286,7 +285,7 @@ class GoRouter extends ChangeNotifier implements RouterConfig { } /// Calls [pop] repeatedly until the predicate returns true. - void popUntil(bool Function(RouteMatch) predicate) { + void popUntil(RoutePredicate predicate) { _routerDelegate.popUntil(predicate); } diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart index 2e453e3523b..14acd8dcb4c 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -67,7 +67,7 @@ void main() { final RouteMatch last = goRouter.routerDelegate.matches.matches.last; int count = 0; - goRouter.popUntil((RouteMatch routeMatch) => count++ >= 2); + goRouter.popUntil((Route routeMatch) => count++ >= 2); expect(goRouter.routerDelegate.matches.matches.length, 1); expect(goRouter.routerDelegate.matches.matches.contains(second), false);