diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 9374421558e0d..519e547189ef5 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 14.2.6 + +- Fixes replace and pushReplacement uri when only one route match in current route match list. + ## 14.2.5 - Fixes an issue where android back button pops pages in the wrong order. diff --git a/packages/go_router/lib/src/parser.dart b/packages/go_router/lib/src/parser.dart index b4115a1fca19c..72f944b0c5a7f 100644 --- a/packages/go_router/lib/src/parser.dart +++ b/packages/go_router/lib/src/parser.dart @@ -160,7 +160,6 @@ class GoRouteInformationParser extends RouteInformationParser { location = safeRoute.matches.uri.toString(); } } - return RouteInformation( uri: Uri.parse(location ?? configuration.uri.toString()), state: _routeMatchListCodec.encode(configuration), @@ -194,22 +193,30 @@ class GoRouteInformationParser extends RouteInformationParser { ); case NavigatingType.pushReplacement: final RouteMatch routeMatch = baseRouteMatchList!.last; - return baseRouteMatchList.remove(routeMatch).push( - ImperativeRouteMatch( - pageKey: _getUniqueValueKey(), - completer: completer!, - matches: newMatchList, - ), - ); + baseRouteMatchList = baseRouteMatchList.remove(routeMatch); + if (baseRouteMatchList.isEmpty) { + return newMatchList; + } + return baseRouteMatchList.push( + ImperativeRouteMatch( + pageKey: _getUniqueValueKey(), + completer: completer!, + matches: newMatchList, + ), + ); case NavigatingType.replace: final RouteMatch routeMatch = baseRouteMatchList!.last; - return baseRouteMatchList.remove(routeMatch).push( - ImperativeRouteMatch( - pageKey: routeMatch.pageKey, - completer: completer!, - matches: newMatchList, - ), - ); + baseRouteMatchList = baseRouteMatchList.remove(routeMatch); + if (baseRouteMatchList.isEmpty) { + return newMatchList; + } + return baseRouteMatchList.push( + ImperativeRouteMatch( + pageKey: routeMatch.pageKey, + completer: completer!, + matches: newMatchList, + ), + ); case NavigatingType.go: return newMatchList; case NavigatingType.restore: diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 2ad6bd28e9039..bef70c82d06b6 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: 14.2.5 +version: 14.2.6 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/extension_test.dart b/packages/go_router/test/extension_test.dart index 0f314edbf66e2..c13a47de002ff 100644 --- a/packages/go_router/test/extension_test.dart +++ b/packages/go_router/test/extension_test.dart @@ -38,9 +38,7 @@ void main() { final GoRouter router = await createGoRouter(tester); await tester.tap(find.text('Settings')); await tester.pumpAndSettle(); - final ImperativeRouteMatch routeMatch = router - .routerDelegate.currentConfiguration.last as ImperativeRouteMatch; - expect(routeMatch.matches.uri.toString(), + expect(router.routerDelegate.currentConfiguration.uri.toString(), '/page-0/settings?search=notification'); }); }); diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index 1a0effb663a49..10e6bb58d5bd6 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -68,6 +68,28 @@ void main() { expect(find.byType(DummyScreen), findsOneWidget); }); + testWidgets('pushReplacement and replace when only one matches', + (WidgetTester tester) async { + final List routes = [ + GoRoute(name: '1', path: '/', builder: dummy), + GoRoute(name: '2', path: '/a', builder: dummy), + GoRoute(name: '3', path: '/b', builder: dummy), + ]; + + final GoRouter router = await createRouter(routes, tester); + expect(router.routerDelegate.currentConfiguration.uri.path, '/'); + + router.replace('/a'); + await tester.pumpAndSettle(); + // When the imperative match is the only match in the route match list, + // it should update the uri. + expect(router.routerDelegate.currentConfiguration.uri.path, '/a'); + + router.pushReplacement('/b'); + await tester.pumpAndSettle(); + expect(router.routerDelegate.currentConfiguration.uri.path, '/b'); + }); + test('empty path', () { expect(() { GoRoute(path: '');