Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
54e1576
Add ShellRoute support to go_router_builder
johnpryan Feb 22, 2023
a52bad2
Fix analysis issues
johnpryan Feb 23, 2023
9797546
Fix go_router_builder test
johnpryan Feb 23, 2023
dadb98f
format
johnpryan Feb 23, 2023
2df6775
Increment minor version
johnpryan Feb 23, 2023
b7441ed
ignore deprected member use so downgraded_analyze step passes
johnpryan Feb 23, 2023
5633d15
Revert old TODO
johnpryan Feb 23, 2023
be0a39f
Skip extensions for ShellRoute
johnpryan Feb 23, 2023
6ed5535
Add GoRouterShellGenerator
GP4cK Mar 10, 2023
ce95e76
Add example
GP4cK Mar 10, 2023
bfa3c2f
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Mar 10, 2023
1e2606f
Lint shell example
GP4cK Mar 10, 2023
632bf68
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Mar 11, 2023
548882a
Revert changes on example/main.dart
GP4cK Mar 11, 2023
7b1305b
Re-run build_runner after merge
GP4cK Mar 11, 2023
75bff09
Fix go_router_builder test
GP4cK Mar 11, 2023
76b9b81
Combine generators
GP4cK Mar 11, 2023
7694e5a
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Mar 11, 2023
4600f37
Use element instead of element2
GP4cK Mar 14, 2023
3efeecd
Removed commented import
GP4cK Mar 14, 2023
fb449ff
Add test on shell_route_example
GP4cK Mar 14, 2023
f0924ed
Remove useless comment
GP4cK Mar 14, 2023
6eab717
Fix navigatorKey vs parentNavigatorKey
GP4cK Mar 14, 2023
9f8b067
Ignore deprecation warning
GP4cK Mar 15, 2023
7f4c6e0
Combine GoRouteGenerator to generate a single $appRoutes
GP4cK Mar 16, 2023
0e48f2a
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Mar 17, 2023
b08bc6d
Fix builder test after merge
GP4cK Mar 17, 2023
4c08623
Merge branch 'flutter:main' into feature/shell-route-go-router-builder
GP4cK Apr 1, 2023
61c3d9d
Use $navigatorKey / $parentNavigatorKey
GP4cK Apr 4, 2023
3013a05
Add example of navigation with keys
GP4cK Apr 4, 2023
3376c73
Add section about navigator keys in README
GP4cK Apr 4, 2023
219f261
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Apr 4, 2023
1832753
Fix linter errors
GP4cK Apr 4, 2023
d7752fd
Add link to example
GP4cK Apr 5, 2023
28e593f
Test shell_route_with_keys_example
GP4cK Apr 5, 2023
6b4ccf1
Merge branch 'main' into feature/shell-route-go-router-builder
GP4cK Apr 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/go_router_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

* Adds Support for ShellRoute

## 1.1.7

* Supports default values for `Set`, `List` and `Iterable` route parameters.
Expand Down
41 changes: 41 additions & 0 deletions packages/go_router_builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,44 @@ class FancyRoute extends GoRouteData {
),
}
```

## TypedShellRoute and navigator keys

There may be situations were a child route of a shell needs to be displayed on a
different navigator. This kind of scenarios can be achieved by declaring a
**static** navigator key named:

- `$navigatorKey` for ShellRoutes
- `$parentNavigatorKey` for GoRoutes

Example:

```dart
// For ShellRoutes:
final GlobalKey<NavigatorState> shellNavigatorKey = GlobalKey<NavigatorState>();

class MyShellRouteData extends ShellRouteData {
const MyShellRouteData();

static final GlobalKey<NavigatorState> $navigatorKey = shellNavigatorKey;

@override
Widget builder(BuildContext context, GoRouterState state, Widget navigator) {
// ...
}
}

// For GoRoutes:
class MyGoRouteData extends GoRouteData {
const MyGoRouteData();

static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;

@override
Widget build(BuildContext context, GoRouterState state) {
// ...
}
}
Copy link
Contributor

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

Copy link
Contributor Author

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.

```

An example is available [here](https://github.com/flutter/packages/blob/main/packages/go_router_builder/example/lib/shell_route_with_keys_example.dart).
4 changes: 2 additions & 2 deletions packages/go_router_builder/example/lib/all_types.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/go_router_builder/example/lib/main.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

153 changes: 153 additions & 0 deletions packages/go_router_builder/example/lib/shell_route_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test in fb449ff

// 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_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: '/foo',
);
}

class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});

@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('foo')),
);
}

@TypedShellRoute<MyShellRouteData>(
Copy link
Contributor

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

Copy link
Contributor Author

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)

Copy link
Contributor

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> ?

Copy link
Contributor Author

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:

  • navigatorKey to TypedShellRoute
  • parentNavigatorKey to TypedGoRoute

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @chunhtai, actually passing the keys as parameters of TypedShellRoute / TypedGoRoute doesn't work because the keys need to be const and GlobalKey<NavigatorState>() is not...
So is it ok to go ahead with this PR as it is now and I'll make another one to revert #3471?

Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

routes: <TypedRoute<RouteData>>[
TypedGoRoute<FooRouteData>(path: '/foo'),
TypedGoRoute<BarRouteData>(path: '/bar'),
],
)
class MyShellRouteData extends ShellRouteData {
const MyShellRouteData();

@override
Widget builder(
BuildContext context,
GoRouterState state,
Widget navigator,
) {
return MyShellRouteScreen(child: navigator);
}
}

class FooRouteData extends GoRouteData {
const FooRouteData();

@override
Widget build(BuildContext context, GoRouterState state) {
return const FooScreen();
}
}

class BarRouteData extends GoRouteData {
const BarRouteData();

@override
Widget build(BuildContext context, GoRouterState state) {
return const BarScreen();
}
}

class MyShellRouteScreen extends StatelessWidget {
const MyShellRouteScreen({required this.child, super.key});

final Widget child;

int getCurrentIndex(BuildContext context) {
final String location = GoRouter.of(context).location;
if (location == '/bar') {
return 1;
}
return 0;
}

@override
Widget build(BuildContext context) {
final int currentIndex = getCurrentIndex(context);
return Scaffold(
body: child,
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Foo',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Bar',
),
],
onTap: (int index) {
switch (index) {
case 0:
const FooRouteData().go(context);
break;
case 1:
const BarRouteData().go(context);
break;
}
},
),
);
}
}

class FooScreen extends StatelessWidget {
const FooScreen({super.key});

@override
Widget build(BuildContext context) {
return const Text('Foo');
}
}

class BarScreen extends StatelessWidget {
const BarScreen({super.key});

@override
Widget build(BuildContext context) {
return const Text('Bar');
}
}

@TypedGoRoute<LoginRoute>(path: '/login')
class LoginRoute extends GoRouteData {
const LoginRoute();

@override
Widget build(BuildContext context, GoRouterState state) =>
const LoginScreen();
}

class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});

@override
Widget build(BuildContext context) {
return const Text('Login');
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading