Skip to content

Commit 0891835

Browse files
authored
[go_router] Added proper redirect handling for ShellRoute.$route and StatefulShellRoute.$route for proper redirection handling in case of code generation (flutter#6841)
Added proper `redirect` handling for `ShellRoute.$route` and `StatefulShellRoute.$route` for proper redirection handling in case of code generation. *List which issues are fixed by this PR. You must list at least one issue.* - I did not create an issue ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] page, which explains my responsibilities. - [x] I read and followed the [relevant style guides] and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use `dart format`.) - [x] I signed the [CLA]. - [x] The title of the PR starts with the name of the package surrounded by square brackets, e.g. `[shared_preferences]` - [ ] I [linked to at least one issue that this PR fixes] in the description above. - [x] I updated `pubspec.yaml` with an appropriate new version according to the [pub versioning philosophy], or this PR is [exempt from version changes]. - [x] I updated `CHANGELOG.md` to add a description of the change, [following repository CHANGELOG style], or this PR is [exempt from CHANGELOG changes]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/packages/blob/main/CONTRIBUTING.md [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [relevant style guides]: https://github.com/flutter/packages/blob/main/CONTRIBUTING.md#style [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md [linked to at least one issue that this PR fixes]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [pub versioning philosophy]: https://dart.dev/tools/pub/versioning [exempt from version changes]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#version [following repository CHANGELOG style]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog-style [exempt from CHANGELOG changes]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests --------- Co-authored-by: Vasiliy Ditsyak <[email protected]>
1 parent 7805455 commit 0891835

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

packages/go_router/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 14.2.0
2+
3+
- Added proper `redirect` handling for `ShellRoute.$route` and `StatefulShellRoute.$route` for proper redirection handling in case of code generation.
4+
15
## 14.1.4
26

37
- Fixes a URL in `navigation.md`.

packages/go_router/lib/src/route_data.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ abstract class ShellRouteData extends RouteData {
159159
'One of `builder` or `pageBuilder` must be implemented.',
160160
);
161161

162+
/// An optional redirect function for this route.
163+
///
164+
/// Subclasses must override one of [build], [buildPage], or
165+
/// [redirect].
166+
///
167+
/// Corresponds to [GoRoute.redirect].
168+
FutureOr<String?> redirect(BuildContext context, GoRouterState state) => null;
169+
162170
/// A helper function used by generated code.
163171
///
164172
/// Should not be used directly.
@@ -174,6 +182,9 @@ abstract class ShellRouteData extends RouteData {
174182
return (_stateObjectExpando[state] ??= factory(state)) as T;
175183
}
176184

185+
FutureOr<String?> redirect(BuildContext context, GoRouterState state) =>
186+
factoryImpl(state).redirect(context, state);
187+
177188
Widget builder(
178189
BuildContext context,
179190
GoRouterState state,
@@ -204,6 +215,7 @@ abstract class ShellRouteData extends RouteData {
204215
navigatorKey: navigatorKey,
205216
observers: observers,
206217
restorationScopeId: restorationScopeId,
218+
redirect: redirect,
207219
);
208220
}
209221

@@ -221,6 +233,14 @@ abstract class StatefulShellRouteData extends RouteData {
221233
/// Default const constructor
222234
const StatefulShellRouteData();
223235

236+
/// An optional redirect function for this route.
237+
///
238+
/// Subclasses must override one of [build], [buildPage], or
239+
/// [redirect].
240+
///
241+
/// Corresponds to [GoRoute.redirect].
242+
FutureOr<String?> redirect(BuildContext context, GoRouterState state) => null;
243+
224244
/// [pageBuilder] is used to build the page
225245
Page<void> pageBuilder(
226246
BuildContext context,
@@ -275,6 +295,9 @@ abstract class StatefulShellRouteData extends RouteData {
275295
navigationShell,
276296
);
277297

298+
FutureOr<String?> redirect(BuildContext context, GoRouterState state) =>
299+
factoryImpl(state).redirect(context, state);
300+
278301
if (navigatorContainerBuilder != null) {
279302
return StatefulShellRoute(
280303
branches: branches,
@@ -283,6 +306,7 @@ abstract class StatefulShellRouteData extends RouteData {
283306
navigatorContainerBuilder: navigatorContainerBuilder,
284307
parentNavigatorKey: parentNavigatorKey,
285308
restorationScopeId: restorationScopeId,
309+
redirect: redirect,
286310
);
287311
}
288312
return StatefulShellRoute.indexedStack(
@@ -291,6 +315,7 @@ abstract class StatefulShellRouteData extends RouteData {
291315
pageBuilder: pageBuilder,
292316
parentNavigatorKey: parentNavigatorKey,
293317
restorationScopeId: restorationScopeId,
318+
redirect: redirect,
294319
);
295320
}
296321

packages/go_router/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: go_router
22
description: A declarative router for Flutter based on Navigation 2 supporting
33
deep linking, data-driven routes and more
4-
version: 14.1.4
4+
version: 14.2.0
55
repository: https://github.com/flutter/packages/tree/main/packages/go_router
66
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
77

packages/go_router/test/route_data_test.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@ import 'package:go_router/go_router.dart';
1010

1111
class _GoRouteDataBuild extends GoRouteData {
1212
const _GoRouteDataBuild();
13+
1314
@override
1415
Widget build(BuildContext context, GoRouterState state) =>
1516
const SizedBox(key: Key('build'));
1617
}
1718

19+
class _ShellRouteDataRedirectPage extends ShellRouteData {
20+
const _ShellRouteDataRedirectPage();
21+
22+
@override
23+
FutureOr<String> redirect(BuildContext context, GoRouterState state) =>
24+
'/build-page';
25+
}
26+
1827
class _ShellRouteDataBuilder extends ShellRouteData {
1928
const _ShellRouteDataBuilder();
2029

@@ -49,7 +58,9 @@ class _ShellRouteDataWithKey extends ShellRouteData {
4958

5059
class _GoRouteDataBuildWithKey extends GoRouteData {
5160
const _GoRouteDataBuildWithKey(this.key);
61+
5262
final Key key;
63+
5364
@override
5465
Widget build(BuildContext context, GoRouterState state) => SizedBox(key: key);
5566
}
@@ -71,6 +82,7 @@ final ShellRoute _shellRouteDataBuilder = ShellRouteData.$route(
7182

7283
class _GoRouteDataBuildPage extends GoRouteData {
7384
const _GoRouteDataBuildPage();
85+
7486
@override
7587
Page<void> buildPage(BuildContext context, GoRouterState state) =>
7688
const MaterialPage<void>(
@@ -95,6 +107,14 @@ class _ShellRouteDataPageBuilder extends ShellRouteData {
95107
);
96108
}
97109

110+
class _StatefulShellRouteDataRedirectPage extends StatefulShellRouteData {
111+
const _StatefulShellRouteDataRedirectPage();
112+
113+
@override
114+
FutureOr<String> redirect(BuildContext context, GoRouterState state) =>
115+
'/build-page';
116+
}
117+
98118
final GoRoute _goRouteDataBuildPage = GoRouteData.$route(
99119
path: '/build-page',
100120
factory: (GoRouterState state) => const _GoRouteDataBuildPage(),
@@ -110,6 +130,21 @@ final ShellRoute _shellRouteDataPageBuilder = ShellRouteData.$route(
110130
],
111131
);
112132

133+
final ShellRoute _shellRouteDataRedirect = ShellRouteData.$route(
134+
factory: (GoRouterState state) => const _ShellRouteDataPageBuilder(),
135+
routes: <RouteBase>[
136+
ShellRouteData.$route(
137+
factory: (GoRouterState state) => const _ShellRouteDataRedirectPage(),
138+
routes: <RouteBase>[
139+
GoRouteData.$route(
140+
path: '/child',
141+
factory: (GoRouterState state) => const _GoRouteDataBuild(),
142+
),
143+
],
144+
),
145+
],
146+
);
147+
113148
class _StatefulShellRouteDataBuilder extends StatefulShellRouteData {
114149
const _StatefulShellRouteDataBuilder();
115150

@@ -174,6 +209,7 @@ final StatefulShellRoute _statefulShellRouteDataPageBuilder =
174209

175210
class _GoRouteDataRedirectPage extends GoRouteData {
176211
const _GoRouteDataRedirectPage();
212+
177213
@override
178214
FutureOr<String> redirect(BuildContext context, GoRouterState state) =>
179215
'/build-page';
@@ -311,6 +347,23 @@ void main() {
311347
expect(find.byKey(const Key('page-builder')), findsOneWidget);
312348
},
313349
);
350+
351+
testWidgets(
352+
'It should redirect using the overridden redirect method',
353+
(WidgetTester tester) async {
354+
final GoRouter goRouter = GoRouter(
355+
initialLocation: '/child',
356+
routes: <RouteBase>[
357+
_goRouteDataBuildPage,
358+
_shellRouteDataRedirect,
359+
],
360+
);
361+
addTearDown(goRouter.dispose);
362+
await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter));
363+
expect(find.byKey(const Key('build')), findsNothing);
364+
expect(find.byKey(const Key('buildPage')), findsOneWidget);
365+
},
366+
);
314367
});
315368

316369
group('StatefulShellRouteData', () {
@@ -381,6 +434,36 @@ void main() {
381434
},
382435
);
383436

437+
testWidgets(
438+
'It should redirect using the overridden StatefulShellRoute redirect method',
439+
(WidgetTester tester) async {
440+
final GoRouter goRouter = GoRouter(
441+
initialLocation: '/child',
442+
routes: <RouteBase>[
443+
_goRouteDataBuildPage,
444+
StatefulShellRouteData.$route(
445+
factory: (GoRouterState state) =>
446+
const _StatefulShellRouteDataRedirectPage(),
447+
branches: <StatefulShellBranch>[
448+
StatefulShellBranchData.$branch(
449+
routes: <GoRoute>[
450+
GoRouteData.$route(
451+
path: '/child',
452+
factory: (GoRouterState state) => const _GoRouteDataBuild(),
453+
),
454+
],
455+
)
456+
],
457+
)
458+
],
459+
);
460+
addTearDown(goRouter.dispose);
461+
await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter));
462+
expect(find.byKey(const Key('build')), findsNothing);
463+
expect(find.byKey(const Key('buildPage')), findsOneWidget);
464+
},
465+
);
466+
384467
testWidgets(
385468
'It should redirect using the overridden redirect method',
386469
(WidgetTester tester) async {

0 commit comments

Comments
 (0)