diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index abb5d9198a7..338fa4db2f1 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 11.1.0 + +- Adds optional parameter `overridePlatformDefaultLocation` to override initial route set by platform. + ## 11.0.1 - Fixes the Android back button ignores top level route's onExit. diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index e37151d4ffe..534581abef3 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -80,6 +80,7 @@ class GoRouter implements RouterConfig { int redirectLimit = 5, bool routerNeglect = false, String? initialLocation, + this.overridePlatformDefaultLocation = false, Object? initialExtra, List? observers, bool debugLogDiagnostics = false, @@ -91,6 +92,8 @@ class GoRouter implements RouterConfig { initialExtra == null || initialLocation != null, 'initialLocation must be set in order to use initialExtra', ), + assert(!overridePlatformDefaultLocation || initialLocation != null, + 'Initial location must be set to override platform default'), assert( (onException == null ? 0 : 1) + (errorPageBuilder == null ? 0 : 1) + @@ -299,6 +302,23 @@ class GoRouter implements RouterConfig { @override late final GoRouteInformationParser routeInformationParser; + /// Whether to ignore platform's default initial location when + /// `initialLocation` is set. + /// + /// When set to [true], the [initialLocation] will take + /// precedence over the platform's default initial location. + /// This allows developers to control the starting route of the application + /// independently of the platform. + /// + /// Platform's initial location is set when the app opens via a deeplink. + /// Use [overridePlatformDefaultLocation] only if one wants to override + /// platform implemented initial location. + /// + /// Setting this parameter to [false] (default) will allow the platform's + /// default initial location to be used even if the `initialLocation` is set. + /// It's advisable to only set this to [true] if one explicitly wants to. + final bool overridePlatformDefaultLocation; + /// Returns `true` if there is at least two or more route can be pop. bool canPop() => routerDelegate.canPop(); @@ -507,6 +527,11 @@ class GoRouter implements RouterConfig { } String _effectiveInitialLocation(String? initialLocation) { + if (overridePlatformDefaultLocation) { + // The initialLocation must not be null as it's already + // verified by assert() during the initialization. + return initialLocation!; + } final String platformDefault = WidgetsBinding.instance.platformDispatcher.defaultRouteName; if (initialLocation == null) { diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 14a0cdcad5e..6dfa7ef007a 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: 11.0.1 +version: 11.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/go_router_test.dart b/packages/go_router/test/go_router_test.dart index 107e828e294..e486129b201 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -4955,6 +4955,60 @@ void main() { expect(statefulWidgetKeyB.currentState?.counter, equals(1)); }); }); + + ///Regression tests for https://github.com/flutter/flutter/issues/132557 + group('overridePlatformDefaultLocation', () { + test('No initial location provided', () { + expect( + () => GoRouter( + overridePlatformDefaultLocation: true, + routes: [ + GoRoute( + path: '/a', + builder: (BuildContext context, GoRouterState state) => + const Placeholder(), + ), + GoRoute( + path: '/b', + builder: (BuildContext context, GoRouterState state) => + const Placeholder(), + ), + ], + ), + throwsA(const TypeMatcher())); + }); + testWidgets('Test override using routeInformationProvider', + (WidgetTester tester) async { + tester.binding.platformDispatcher.defaultRouteNameTestValue = + '/some-route'; + final String platformRoute = + WidgetsBinding.instance.platformDispatcher.defaultRouteName; + const String expectedInitialRoute = '/kyc'; + expect(platformRoute != expectedInitialRoute, isTrue); + + final List routes = [ + GoRoute( + path: '/abc', + builder: (BuildContext context, GoRouterState state) => + const Placeholder(), + ), + GoRoute( + path: '/bcd', + builder: (BuildContext context, GoRouterState state) => + const Placeholder(), + ), + ]; + + final GoRouter router = await createRouter( + routes, + tester, + overridePlatformDefaultLocation: true, + initialLocation: expectedInitialRoute, + ); + expect(router.routeInformationProvider.value.uri.toString(), + expectedInitialRoute); + }); + }); } class TestInheritedNotifier extends InheritedNotifier> { diff --git a/packages/go_router/test/test_helpers.dart b/packages/go_router/test/test_helpers.dart index 38420cd2913..650fa13a2af 100644 --- a/packages/go_router/test/test_helpers.dart +++ b/packages/go_router/test/test_helpers.dart @@ -150,6 +150,7 @@ Future createRouter( String? restorationScopeId, GoExceptionHandler? onException, bool requestFocus = true, + bool overridePlatformDefaultLocation = false, }) async { final GoRouter goRouter = GoRouter( routes: routes, @@ -162,6 +163,7 @@ Future createRouter( navigatorKey: navigatorKey, restorationScopeId: restorationScopeId, requestFocus: requestFocus, + overridePlatformDefaultLocation: overridePlatformDefaultLocation, ); await tester.pumpWidget( MaterialApp.router(