diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 2ddd57a06ea..465df984b23 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.3 + +- Fixes a bug where the ValueKey to be the same when a page was pushed multiple times. + ## 4.2.2 - Fixes a bug where go_router_builder wasn't detecting annotations. diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 1af969c5376..29f0f251f33 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -45,10 +45,27 @@ class GoRouterDelegate extends RouterDelegate final GlobalKey _key = GlobalKey(); RouteMatchList _matches = RouteMatchList.empty(); + final Map _pushCounts = {}; - /// Push the given location onto the page stack + /// Pushes the given location onto the page stack void push(RouteMatch match) { - _matches.push(match); + // Remap the pageKey to allow any number of the same page on the stack + final String fullPath = match.fullpath; + final int count = (_pushCounts[fullPath] ?? 0) + 1; + _pushCounts[fullPath] = count; + final ValueKey pageKey = ValueKey('$fullPath-p$count'); + final RouteMatch newPageKeyMatch = RouteMatch( + route: match.route, + subloc: match.subloc, + fullpath: match.fullpath, + encodedParams: match.encodedParams, + queryParams: match.queryParams, + extra: match.extra, + error: match.error, + pageKey: pageKey, + ); + + _matches.push(newPageKeyMatch); notifyListeners(); } diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 4c8da3d9c5f..0b2d6f0279f 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: 4.2.2 +version: 4.2.3 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 a85d53668a3..b4a417368e0 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -16,6 +16,7 @@ Future createGoRouter( initialLocation: '/', routes: [ GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute(path: '/a', builder: (_, __) => const DummyStatefulWidget()), GoRoute( path: '/error', builder: (_, __) => const ErrorScreen(null), @@ -56,6 +57,38 @@ void main() { }); }); + group('push', () { + testWidgets( + 'It should return different pageKey when push is called', + (WidgetTester tester) async { + final GoRouter goRouter = await createGoRouter(tester); + expect(goRouter.routerDelegate.matches.matches.length, 1); + expect( + goRouter.routerDelegate.matches.matches[0].pageKey, + null, + ); + + goRouter.push('/a'); + await tester.pumpAndSettle(); + + expect(goRouter.routerDelegate.matches.matches.length, 2); + expect( + goRouter.routerDelegate.matches.matches[1].pageKey, + const Key('/a-p1'), + ); + + goRouter.push('/a'); + await tester.pumpAndSettle(); + + expect(goRouter.routerDelegate.matches.matches.length, 3); + expect( + goRouter.routerDelegate.matches.matches[2].pageKey, + const Key('/a-p2'), + ); + }, + ); + }); + group('canPop', () { testWidgets( 'It should return false if there is only 1 match in the stack',