-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[go_router_builder] Add ShellRoute support to go_router_builder #3439
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 ShellRoute support to go_router_builder #3439
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
|
As mentioned in the other PR, please let me know how you want me to refactor the |
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it will be better if we can refactor GoRouterGenerator to prevent code duplication. I imagine we will add more shellroute subclass in the future
|
|
||
| extension $FamilyRouteExtension on FamilyRoute { | ||
| static FamilyRoute _fromState(GoRouterState state) => FamilyRoute( | ||
| static FamilyRoute _fromState(GoRouterState state) => const FamilyRoute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feel a bit unnecessary? maybe we don't need to generate extension for shellRoute at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change got reverted with the changes on example/lib/main.dart but if you're talking more generally about the ShellRouteExtension._fromState, it is passed as the factory of ShellRouteData.$route to create $appRoutes.
I've refactored the generator in 76b9b81, let me know what you think. For the tests, I'm not sure what is the most pertinent. It seems most of the code is already covered by |
dorklein
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good
alanchan-dev
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks good.
| @@ -0,0 +1,134 @@ | |||
| // Copyright 2013 The Flutter Authors. All rights reserved. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a simple test for this example? Just make sure things will compile and the shellRoute's widget is built
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added test in fb449ff
| ); | ||
| } | ||
|
|
||
| @TypedShellRoute<MyShellRouteData>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have missed something, how would one specified navigator key for typedshellRoute and also the parent navigator key for typedGoRoute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what @johnpryan had in mind was to add a static final or getter called $navigatorKey to the class extending ShellRouteData and GoRouteData and this will be grabbed by the _decodeKey and added as the navigatorKey / parentNavigatorKey (BTW I fixed a small bug here: 6eab717)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static final or getter
It seems a bit not obvious. Why not just let it be a parameter into the
@TypedShellRoute<MyShellRouteData> ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it's not obvious. I assumed that you two had agreed on the approach beforehand and I just picked up the work where it was left off.
So if we go ahead with adding:
navigatorKeytoTypedShellRouteparentNavigatorKeytoTypedGoRoute
I will first need to make a PR on go_router (since that's where these classes are defined) and then raise the minimum version of go_router in go_router_builder.
Could you confirm that it's ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that is ok. Sorry about the miscommunication, the original PR was still in its initial state, so there may be some issue that hasn't been discovered yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I also should have double checked.
Here is the PR on go_router for the first step: #3471
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain a bit why it needs to be const? I can't find the places the enforce the requirement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
I just learned from @johnpryan that annotation has to be const. Let me think a bit on what else we can do here... |
|
Yes, annotations must have a |
I will give a try to this PR since I built around everything with |
|
After some thought, I think we can have a getter in the GoRouteData and ShellRouteData for example: and user can override and provide their navigator key in the subclass if they want. I was hoping this would be more clear than using the static field. At least people can see the getter in the abstract class and notice such thing exists. WDYT @johnpryan @GP4cK |
|
I'm good with that and it's not too far from the initial implementation. EDIT: actually the problem is that if the keys are non-static getters, I don't know how to invoke the getter or get the name of the variable returned by it in the generated code. For example, in this code: final GlobalKey<NavigatorState> goRouteKey = GlobalKey<NavigatorState>();
class GoRouteWithKey extends GoRouteData {
const GoRouteWithKey();
@override
GlobalKey<NavigatorState>? get navigatorKey => goRouteKey;
}In the classElement.fields
.where(whereKeyName)
.where((FieldElement element) {
final DartType type = element.type;
if (type is! ParameterizedType) {
return false;
}
final List<DartType> typeArguments = type.typeArguments;
if (typeArguments.length != 1) {
return false;
}
final DartType typeArgument = typeArguments.single;
if (typeArgument.getDisplayString(withNullability: false) ==
'NavigatorState') {
return true;
}
return false;
})But once we have the ref to the |
|
I have a question regarding Apparently, to run this flow, I should put Codefinal GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> _shellNavigatorKey = GlobalKey<NavigatorState>();
final router = GoRouter(
navigatorKey: _navigatorKey,
initialLocation: AppRoutes.SPLASH,
observers: [NavigatorObservers()],
routes: $appRoutes,
);
/// Splash Route
@immutable
@TypedGoRoute<SplashViewRoute>(path: AppRoutes.SPLASH, routes: [])
class SplashViewRoute extends GoRouteData {
const SplashViewRoute();
@override
Widget build(BuildContext _, GoRouterState state) => const SplashView();
}
///
/// Home Route
@TypedShellRoute(
routes: [
TypedGoRoute<SubViewRoute>(path: AppRoutes.HOME),
],
)
class HomeViewRoute extends ShellRouteData {
const HomeViewRoute();
@override
Widget builder(BuildContext context, GoRouterState state, Widget navigator) => const SizedBox.shrink();
@override
GlobalKey<NavigatorState>? get navigatorKey => _shellNavigatorKey;
}
class SubViewRoute extends GoRouteData {
const SubViewRoute();
@override
Widget build(BuildContext _, GoRouterState state) => const SizedBox.shrink();
@override
GlobalKey<NavigatorState>? get navigatorKey => _shellNavigatorKey;
}
If I turned I am getting this error when I tried to generate a code: edit: pubspec.yaml environment:
sdk: ">=2.19.5 <3.0.0"
flutter: 3.7.9
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
# Routing
go_router: 6.5.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
# Code Generation
analyzer: 5.10.0
build_runner: 2.3.3
build_verify: 3.1.0
# Builders
# TODO: do not forget to change this to upstream when its merged
go_router_builder:
git:
url: [email protected]:GP4cK/packages.git
path: packages/go_router_builder
ref: feature/shell-route-go-router-builder
flutter:
uses-material-design: true |
@kaankoken, I copy/pasted your code in the example, ran the generator and it did generate some code. The only line I modified was /// Home Route
-@TypedShellRoute(
+@TypedShellRoute<HomeViewRoute>(Also, I see that you're overriding the -@override
-GlobalKey<NavigatorState>? get navigatorKey => _shellNavigatorKey;
+static final GlobalKey<NavigatorState> $navigatorKey = _shellNavigatorKey; |
|
yeah I was confused myself how |
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the work, I left some comments, but overall looks great.
Can you add a section in readme to talk about shellroute and navigatorkey?
| final String navigatorKeyParameterName = | ||
| _isShellRoute ? 'navigatorKey' : 'parentNavigatorKey'; | ||
| final String navigatorKey = _key == null || _key!.isEmpty | ||
| ? '' | ||
| : '$navigatorKeyParameterName: $_key,'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just add an example in the example folder, and add a test for that example to make sure everything works correctly. We also have a test to ensure the .g.dart is always the latest code. So if someone breaks the route_config.dart either the example test will fail or the .g.dart test will fail.
| provider: 6.0.5 | ||
|
|
||
| dev_dependencies: | ||
| build_runner: ^2.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this need to be a 2.3.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I change it to build_runner: 2.0.0 and run flutter clean && flutter pub get, I get this error:
Because every version of go_router_builder from path depends on analyzer >=4.4.0 <6.0.0 and build_runner >=2.0.0 <2.0.6 depends on analyzer ^1.4.0, go_router_builder from path is incompatible
with build_runner >=2.0.0 <2.0.6.
Similar issue with 2.1.0. However 2.2.0 works fine. Shall I change to ^2.2.0? This is just the pubspec in the example folder so I don't think it makes much of a difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, this is fine then
| @@ -0,0 +1,169 @@ | |||
| // Copyright 2013 The Flutter Authors. All rights reserved. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a test for this? just to make sure the code can actually compile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a simple test here: Test shell_route_with_keys_example
| Widget build(BuildContext context, GoRouterState state) { | ||
| // ... | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also add a link to the examples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the link here: Add link to example
It will work when the PR is merged.
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| InterfaceElement classElement, { | ||
| required String keyName, | ||
| }) { | ||
| bool whereStatic(FieldElement element) => element.isStatic; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why create one-off functions for the tiny ones – but keep the big function inline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No strong reason I believe.
Do you want me to make a PR to make everything inline?
Do I need to create an issue for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No issue needed. just a cleanup PR. I'd put everything inline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I grouped everything under one .where #3698
…ter#3439) [go_router_builder] Add ShellRoute support to go_router_builder

Continuing the work of #3269
Fixes flutter/flutter#111909
Pre-launch Checklist
dart format.)[shared_preferences]pubspec.yamlwith an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.mdto add a description of the change, following repository CHANGELOG style.///).If you need help, consider asking for advice on the #hackers-new channel on Discord.