-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[go_router_builder] add support to go_router_builder for initializing a ShellRoute with observers
#5563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[go_router_builder] add support to go_router_builder for initializing a ShellRoute with observers
#5563
Changes from 10 commits
622e270
de305a6
9c46f95
eec44ef
d1a222d
79764d5
013eead
601f39b
2e53d94
6ab2fc6
b76c843
2db3d19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // ignore_for_file: public_member_api_docs | ||
|
|
||
| import 'package:flutter/material.dart'; | ||
| import 'package:go_router/go_router.dart'; | ||
|
|
||
| part 'shell_route_with_observers_example.g.dart'; | ||
|
|
||
| void main() => runApp(App()); | ||
|
|
||
| class App extends StatelessWidget { | ||
| App({super.key}); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) => MaterialApp.router( | ||
| routerConfig: _router, | ||
| ); | ||
|
|
||
| final GoRouter _router = GoRouter( | ||
| routes: $appRoutes, | ||
| initialLocation: '/home', | ||
| ); | ||
| } | ||
|
|
||
| @TypedShellRoute<MyShellRouteData>( | ||
| routes: <TypedRoute<RouteData>>[ | ||
| TypedGoRoute<HomeRouteData>(path: '/home'), | ||
| TypedGoRoute<UsersRouteData>( | ||
| path: '/users', | ||
| routes: <TypedGoRoute<UserRouteData>>[ | ||
| TypedGoRoute<UserRouteData>(path: ':id'), | ||
| ], | ||
| ), | ||
| ], | ||
| ) | ||
| class MyShellRouteData extends ShellRouteData { | ||
| const MyShellRouteData(); | ||
|
|
||
| static final List<NavigatorObserver> $observers = <NavigatorObserver>[ | ||
| MyNavigatorObserver() | ||
| ]; | ||
|
|
||
| @override | ||
| Widget builder(BuildContext context, GoRouterState state, Widget navigator) { | ||
| return MyShellRouteScreen(child: navigator); | ||
| } | ||
| } | ||
|
|
||
| class MyNavigatorObserver extends NavigatorObserver { | ||
| @override | ||
| void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {} | ||
| } | ||
|
|
||
| class MyShellRouteScreen extends StatelessWidget { | ||
| const MyShellRouteScreen({required this.child, super.key}); | ||
|
|
||
| final Widget child; | ||
|
|
||
| int getCurrentIndex(BuildContext context) { | ||
| final String location = GoRouterState.of(context).uri.toString(); | ||
| if (location.startsWith('/users')) { | ||
| return 1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| final int selectedIndex = getCurrentIndex(context); | ||
|
|
||
| return Scaffold( | ||
| body: Row( | ||
| children: <Widget>[ | ||
| NavigationRail( | ||
| destinations: const <NavigationRailDestination>[ | ||
| NavigationRailDestination( | ||
| icon: Icon(Icons.home), | ||
| label: Text('Home'), | ||
| ), | ||
| NavigationRailDestination( | ||
| icon: Icon(Icons.group), | ||
| label: Text('Users'), | ||
| ), | ||
| ], | ||
| selectedIndex: selectedIndex, | ||
| onDestinationSelected: (int index) { | ||
| switch (index) { | ||
| case 0: | ||
| const HomeRouteData().go(context); | ||
| break; | ||
| case 1: | ||
| const UsersRouteData().go(context); | ||
| break; | ||
| } | ||
| }, | ||
| ), | ||
| const VerticalDivider(thickness: 1, width: 1), | ||
| Expanded(child: child), | ||
| ], | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| class HomeRouteData extends GoRouteData { | ||
| const HomeRouteData(); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context, GoRouterState state) { | ||
| return const Center(child: Text('The home page')); | ||
| } | ||
| } | ||
|
|
||
| class UsersRouteData extends GoRouteData { | ||
| const UsersRouteData(); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context, GoRouterState state) { | ||
| return ListView( | ||
| children: <Widget>[ | ||
| for (int userID = 1; userID <= 3; userID++) | ||
| ListTile( | ||
| title: Text('User $userID'), | ||
| onTap: () => UserRouteData(id: userID).go(context), | ||
| ), | ||
| ], | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| class DialogPage extends Page<void> { | ||
| /// A page to display a dialog. | ||
| const DialogPage({required this.child, super.key}); | ||
|
|
||
| /// The widget to be displayed which is usually a [Dialog] widget. | ||
| final Widget child; | ||
|
|
||
| @override | ||
| Route<void> createRoute(BuildContext context) { | ||
| return DialogRoute<void>( | ||
| context: context, | ||
| settings: this, | ||
| builder: (BuildContext context) => child, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| class UserRouteData extends GoRouteData { | ||
| const UserRouteData({required this.id}); | ||
|
|
||
| // Without this static key, the dialog will not cover the navigation rail. | ||
| final int id; | ||
|
|
||
| @override | ||
| Page<void> buildPage(BuildContext context, GoRouterState state) { | ||
| return DialogPage( | ||
| key: state.pageKey, | ||
| child: Center( | ||
| child: SizedBox( | ||
| width: 300, | ||
| height: 300, | ||
| child: Card(child: Center(child: Text('User $id'))), | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ class ShellRouteConfig extends RouteBaseConfig { | |
| required this.navigatorKey, | ||
| required this.parentNavigatorKey, | ||
| required super.routeDataClass, | ||
| required this.observers, | ||
| required super.parent, | ||
| }) : super._(); | ||
|
|
||
|
|
@@ -49,6 +50,9 @@ class ShellRouteConfig extends RouteBaseConfig { | |
| /// The parent navigator key. | ||
| final String? parentNavigatorKey; | ||
|
|
||
| /// The navigator observers. | ||
| final String? observers; | ||
|
|
||
| @override | ||
| Iterable<String> classDeclarations() { | ||
| if (routeDataClass.unnamedConstructor == null) { | ||
|
|
@@ -72,7 +76,8 @@ class ShellRouteConfig extends RouteBaseConfig { | |
| @override | ||
| String get routeConstructorParameters => | ||
| '${navigatorKey == null ? '' : 'navigatorKey: $navigatorKey,'}' | ||
| '${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'}'; | ||
| '${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'}' | ||
| '${observers == null ? '' : 'observers: $observers,'}'; | ||
|
|
||
| @override | ||
| String get factorConstructorParameters => | ||
|
|
@@ -475,6 +480,10 @@ abstract class RouteBaseConfig { | |
| classElement, | ||
| parameterName: r'$parentNavigatorKey', | ||
| ), | ||
| observers: _generateParameterGetterCode( | ||
| classElement, | ||
| parameterName: r'$observers', | ||
| ), | ||
| ); | ||
| break; | ||
| case 'TypedStatefulShellRoute': | ||
|
|
@@ -568,7 +577,9 @@ abstract class RouteBaseConfig { | |
| if (!element.isStatic || element.name != parameterName) { | ||
| return false; | ||
| } | ||
| if (parameterName.toLowerCase().contains('navigatorkey')) { | ||
| if (parameterName | ||
| .toLowerCase() | ||
| .contains(RegExp('navigatorKey | observers'))) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this no longer match against |
||
| final DartType type = element.type; | ||
| if (type is! ParameterizedType) { | ||
| return false; | ||
|
|
@@ -591,7 +602,6 @@ abstract class RouteBaseConfig { | |
| if (fieldDisplayName != null) { | ||
| return '${classElement.name}.$fieldDisplayName'; | ||
| } | ||
|
|
||
| final String? methodDisplayName = classElement.methods | ||
| .where((MethodElement element) { | ||
| return element.isStatic && element.name == parameterName; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.