[GoRouter] option to override initial route set by platform (#4717)
Added optional parameter to override platform route mentioned in `MainActivity.kt`.
This would be completely optional and caters to a very edge-case, but providing an option to would be best.
This PR will fix https://github.com/flutter/flutter/issues/132402 & Feature Req flutter/flutter#132557
All existing tests pass, no breaking changes.
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index abb5d91..338fa4d 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 e37151d..534581a 100644
--- a/packages/go_router/lib/src/router.dart
+++ b/packages/go_router/lib/src/router.dart
@@ -80,6 +80,7 @@
int redirectLimit = 5,
bool routerNeglect = false,
String? initialLocation,
+ this.overridePlatformDefaultLocation = false,
Object? initialExtra,
List<NavigatorObserver>? observers,
bool debugLogDiagnostics = false,
@@ -91,6 +92,8 @@
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 @@
@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 @@
}
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 14a0cdc..6dfa7ef 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 107e828..e486129 100644
--- a/packages/go_router/test/go_router_test.dart
+++ b/packages/go_router/test/go_router_test.dart
@@ -4955,6 +4955,60 @@
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: <RouteBase>[
+ GoRoute(
+ path: '/a',
+ builder: (BuildContext context, GoRouterState state) =>
+ const Placeholder(),
+ ),
+ GoRoute(
+ path: '/b',
+ builder: (BuildContext context, GoRouterState state) =>
+ const Placeholder(),
+ ),
+ ],
+ ),
+ throwsA(const TypeMatcher<AssertionError>()));
+ });
+ 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<RouteBase> routes = <RouteBase>[
+ 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<ValueNotifier<String>> {
diff --git a/packages/go_router/test/test_helpers.dart b/packages/go_router/test/test_helpers.dart
index 38420cd..650fa13 100644
--- a/packages/go_router/test/test_helpers.dart
+++ b/packages/go_router/test/test_helpers.dart
@@ -150,6 +150,7 @@
String? restorationScopeId,
GoExceptionHandler? onException,
bool requestFocus = true,
+ bool overridePlatformDefaultLocation = false,
}) async {
final GoRouter goRouter = GoRouter(
routes: routes,
@@ -162,6 +163,7 @@
navigatorKey: navigatorKey,
restorationScopeId: restorationScopeId,
requestFocus: requestFocus,
+ overridePlatformDefaultLocation: overridePlatformDefaultLocation,
);
await tester.pumpWidget(
MaterialApp.router(