Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
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.1

* Support for the generation of the pushReplacement method has been added.
Expand Down
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.

67 changes: 52 additions & 15 deletions packages/go_router_builder/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class App extends StatelessWidget {
late final GoRouter _router = GoRouter(
debugLogDiagnostics: true,
routes: $appRoutes,
navigatorKey: key,

// redirect to the login page if the user is not logged in
redirect: (BuildContext context, GoRouterState state) {
Expand Down Expand Up @@ -63,20 +64,26 @@ class App extends StatelessWidget {
);
}

const GlobalObjectKey<NavigatorState> key = GlobalObjectKey('navigator_key');

@TypedGoRoute<HomeRoute>(
path: '/',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<FamilyRoute>(
path: 'family/:fid',
routes: <TypedShellRoute<FamilyRoute>>[
TypedShellRoute<FamilyRoute>(
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<PersonRoute>(
path: 'person/:pid',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<PersonDetailsRoute>(path: 'details/:details'),
TypedGoRoute<FamilyIdRoute>(
path: 'family/:fid',
routes: <TypedGoRoute<PersonRoute>>[
TypedGoRoute<PersonRoute>(
path: 'person/:pid',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<PersonDetailsRoute>(path: 'details/:details'),
],
),
],
),
],
)
),
],
)
class HomeRoute extends GoRouteData {
Expand All @@ -86,6 +93,17 @@ class HomeRoute extends GoRouteData {
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
}

class FamilyRoute extends ShellRouteData {
const FamilyRoute();

static final GlobalKey<NavigatorState> $navigatorKey = GlobalKey();

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

@TypedGoRoute<LoginRoute>(
path: '/login',
)
Expand All @@ -99,14 +117,15 @@ class LoginRoute extends GoRouteData {
LoginScreen(from: fromPage);
}

class FamilyRoute extends GoRouteData {
const FamilyRoute(this.fid);
class FamilyIdRoute extends GoRouteData {
const FamilyIdRoute(this.fid);

final String fid;

@override
Widget build(BuildContext context, GoRouterState state) =>
FamilyScreen(family: familyById(fid));
Widget build(BuildContext context, GoRouterState state) => FamilyIdScreen(
family: familyById(fid),
);
}

class PersonRoute extends GoRouteData {
Expand Down Expand Up @@ -177,7 +196,7 @@ class HomeScreen extends StatelessWidget {
for (final Family f in familyData)
ListTile(
title: Text(f.name),
onTap: () => FamilyRoute(f.id).go(context),
onTap: () => FamilyIdRoute(f.id).go(context),
)
],
),
Expand All @@ -186,7 +205,23 @@ class HomeScreen extends StatelessWidget {
}

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

final Widget child;

@override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.all(20),
child: child,
);
}

class FamilyIdScreen extends StatelessWidget {
const FamilyIdScreen({required this.family, super.key});

final Family family;

@override
Expand Down Expand Up @@ -225,7 +260,8 @@ class PersonScreen extends StatelessWidget {
in person.details.entries)
ListTile(
title: Text(
'${entry.key.name} - ${entry.value}',
// TODO(kevmoo): replace `split` with `name` when min SDK is 2.15

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be reverted?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch

'${entry.key.toString().split('.').last} - ${entry.value}',
),
trailing: OutlinedButton(
onPressed: () => PersonDetailsRoute(
Expand Down Expand Up @@ -279,6 +315,7 @@ class PersonDetailsPage extends StatelessWidget {

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

final String? from;

@override
Expand Down
41 changes: 31 additions & 10 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.

4 changes: 2 additions & 2 deletions packages/go_router_builder/example/lib/simple_example.g.dart

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

2 changes: 1 addition & 1 deletion packages/go_router_builder/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
provider: ^6.0.0

dev_dependencies:
build_runner: ^2.0.0
build_runner: ^2.3.0
build_verify: ^3.1.0
flutter_test:
sdk: flutter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class GoRouterGenerator extends GeneratorForAnnotation<void> {

return <String>[
'''
List<GoRoute> get \$appRoutes => [
List<RouteBase> get \$appRoutes => [
${getters.map((String e) => "$e,").join('\n')}
];
''',
Expand Down
86 changes: 72 additions & 14 deletions packages/go_router_builder/lib/src/route_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class RouteConfig {
this._path,
this._routeDataClass,
this._parent,
this._key,
this._isShellRoute,
);

/// Creates a new [RouteConfig] represented the annotation data in [reader].
Expand Down Expand Up @@ -66,19 +68,26 @@ class RouteConfig {
RouteConfig? parent,
) {
assert(!reader.isNull, 'reader should not be null');
final ConstantReader pathValue = reader.read('path');
if (pathValue.isNull) {
throw InvalidGenerationSourceError(
'Missing `path` value on annotation.',
element: element,
);
}
final InterfaceType type = reader.objectValue.type! as InterfaceType;
// Ignore the deprected `element2` so that the "downgraded_analyze" CI step
// passes.
//ignore: deprecated_member_use
final bool isShellRoute = type.element2.name == 'TypedShellRoute';

final String path = pathValue.stringValue;
String? path;

final InterfaceType type = reader.objectValue.type! as InterfaceType;
final DartType typeParamType = type.typeArguments.single;
if (!isShellRoute) {
final ConstantReader pathValue = reader.read('path');
if (pathValue.isNull) {
throw InvalidGenerationSourceError(
'Missing `path` value on annotation.',
element: element,
);
}
path = pathValue.stringValue;
}

final DartType typeParamType = type.typeArguments.single;
if (typeParamType is! InterfaceType) {
throw InvalidGenerationSourceError(
'The type parameter on one of the @TypedGoRoute declarations could not '
Expand All @@ -93,18 +102,56 @@ class RouteConfig {
// ignore: deprecated_member_use
final InterfaceElement classElement = typeParamType.element;

final RouteConfig value = RouteConfig._(path, classElement, parent);
final RouteConfig value = RouteConfig._(
path ?? '',
classElement,
parent,
_decodeKey(classElement),
isShellRoute,
);

value._children.addAll(reader.read('routes').listValue.map((DartObject e) =>
RouteConfig._fromAnnotation(ConstantReader(e), element, value)));

return value;
}

final List<RouteConfig> _children = <RouteConfig>[];
final String _path;
final InterfaceElement _routeDataClass;
final RouteConfig? _parent;
final String? _key;
final bool _isShellRoute;

static String? _decodeKey(InterfaceElement classElement) {
bool whereStatic(FieldElement element) => element.isStatic;
bool whereKeyName(FieldElement element) => element.name == r'$navigatorKey';
final String? fieldDisplayName = classElement.fields
.where(whereStatic)
.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;
})
.map<String>((FieldElement e) => e.displayName)
.firstOrNull;

if (fieldDisplayName == null) {
return null;
}
return '${classElement.name}.$fieldDisplayName';
}

/// Generates all of the members that correspond to `this`.
InfoIterable generateMembers() => InfoIterable._(
Expand Down Expand Up @@ -164,7 +211,7 @@ extension $_extensionName on $_className {

/// Returns the `GoRoute` code for the annotated class.
String _rootDefinition() => '''
GoRoute get $_routeGetterName => ${_routeDefinition()};
RouteBase get $_routeGetterName => ${_routeDefinition()};
''';

/// Returns code representing the constant maps that contain the `enum` to
Expand Down Expand Up @@ -257,11 +304,22 @@ GoRoute get $_routeGetterName => ${_routeDefinition()};
: '''
routes: [${_children.map((RouteConfig e) => '${e._routeDefinition()},').join()}],
''';

final String navigatorKey =
_key == null || _key!.isEmpty ? '' : 'navigatorKey: $_key,';
if (_isShellRoute) {
return '''
ShellRouteData.\$route(
factory: $_extensionName._fromState,
$navigatorKey
$routesBit
)
''';
}
return '''
GoRouteData.\$route(
path: ${escapeDartString(_path)},
factory: $_extensionName._fromState,
$navigatorKey
$routesBit
)
''';
Expand Down
Loading