Skip to content

Commit

Permalink
[go_router_builder] Add support for Iterable, List and Set to TypedGo…
Browse files Browse the repository at this point in the history
…Route (flutter#2679)

* fixes #108437 support for iterable, list and set

* fixes #108437 url encoding for iterable, list and set

* fixes #108437 tests

* format and analysis fix

* fix string encoding

* format

* removed unused helper name

* fix nullability checks for query params encoding

* fix all_types.dart for new go router version

* rebased to upstream

* version

* missing file regeneration
  • Loading branch information
Skogsfrae authored and navaronbracke committed Mar 3, 2023
1 parent 8259288 commit 8d0ab2c
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 15 deletions.
4 changes: 4 additions & 0 deletions packages/go_router_builder/CHANGELOG.md
@@ -1,3 +1,7 @@
## 1.1.2

* Adds support for Iterables, Lists and Sets in query params for TypedGoRoute. [#108437](https://github.com/flutter/flutter/issues/108437).

## 1.1.1

* Support for the generation of the pushReplacement method has been added.
Expand Down
84 changes: 81 additions & 3 deletions packages/go_router_builder/example/lib/all_types.dart
Expand Up @@ -24,6 +24,7 @@ part 'all_types.g.dart';
path: 'enhanced-enum-route/:requiredEnumField'),
TypedGoRoute<StringRoute>(path: 'string-route/:requiredStringField'),
TypedGoRoute<UriRoute>(path: 'uri-route/:requiredUriField'),
TypedGoRoute<IterableRoute>(path: 'iterable-route'),
])
@immutable
class AllTypesBaseRoute extends GoRouteData {
Expand All @@ -33,7 +34,6 @@ class AllTypesBaseRoute extends GoRouteData {
Widget build(BuildContext context, GoRouterState state) =>
const BasePage<void>(
dataTitle: 'Root',
param: null,
);
}

Expand Down Expand Up @@ -290,17 +290,69 @@ class UriRoute extends GoRouteData {
);
}

class IterableRoute extends GoRouteData {
IterableRoute({
this.intIterableField,
this.doubleIterableField,
this.stringIterableField,
this.boolIterableField,
this.enumIterableField,
this.intListField,
this.doubleListField,
this.stringListField,
this.boolListField,
this.enumListField,
this.intSetField,
this.doubleSetField,
this.stringSetField,
this.boolSetField,
this.enumSetField,
});

final Iterable<int>? intIterableField;
final List<int>? intListField;
final Set<int>? intSetField;

final Iterable<double>? doubleIterableField;
final List<double>? doubleListField;
final Set<double>? doubleSetField;

final Iterable<String>? stringIterableField;
final List<String>? stringListField;
final Set<String>? stringSetField;

final Iterable<bool>? boolIterableField;
final List<bool>? boolListField;
final Set<bool>? boolSetField;

final Iterable<SportDetails>? enumIterableField;
final List<SportDetails>? enumListField;
final Set<SportDetails>? enumSetField;

@override
Widget build(BuildContext context, GoRouterState state) =>
const BasePage<String>(
dataTitle: 'IterableRoute',
);

Widget drawerTile(BuildContext context) => ListTile(
title: const Text('IterableRoute'),
onTap: () => go(context),
selected: GoRouter.of(context).location == location,
);
}

class BasePage<T> extends StatelessWidget {
const BasePage({
required this.dataTitle,
required this.param,
this.param,
this.queryParam,
this.queryParamWithDefaultValue,
super.key,
});

final String dataTitle;
final T param;
final T? param;
final T? queryParam;
final T? queryParamWithDefaultValue;

Expand Down Expand Up @@ -352,6 +404,32 @@ class BasePage<T> extends StatelessWidget {
requiredUriField: Uri.parse('https://dart.dev'),
uriField: Uri.parse('https://dart.dev'),
).drawerTile(context),
IterableRoute(
intIterableField: <int>[1, 2, 3],
doubleIterableField: <double>[.3, .4, .5],
stringIterableField: <String>['quo usque tandem'],
boolIterableField: <bool>[true, false, false],
enumIterableField: <SportDetails>[
SportDetails.football,
SportDetails.hockey,
],
intListField: <int>[1, 2, 3],
doubleListField: <double>[.3, .4, .5],
stringListField: <String>['quo usque tandem'],
boolListField: <bool>[true, false, false],
enumListField: <SportDetails>[
SportDetails.football,
SportDetails.hockey,
],
intSetField: <int>{1, 2, 3},
doubleSetField: <double>{.3, .4, .5},
stringSetField: <String>{'quo usque tandem'},
boolSetField: <bool>{true, false},
enumSetField: <SportDetails>{
SportDetails.football,
SportDetails.hockey,
},
).drawerTile(context),
],
)),
body: Center(
Expand Down
109 changes: 104 additions & 5 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.

2 changes: 1 addition & 1 deletion 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.

10 changes: 10 additions & 0 deletions packages/go_router_builder/example/test/all_types_test.dart
Expand Up @@ -125,5 +125,15 @@ void main() {
expect(find.text('UriRoute'), findsOneWidget);
expect(find.text('Param: https://dart.dev'), findsOneWidget);
expect(find.text('Query param: https://dart.dev'), findsOneWidget);

IterableRoute(
intListField: <int>[1, 2, 3],
).go(scaffoldState.context);
await tester.pumpAndSettle();
expect(find.text('IterableRoute'), findsOneWidget);
expect(
find.text(
'/iterable-route?int-list-field=1&int-list-field=2&int-list-field=3'),
findsOneWidget);
});
}
5 changes: 4 additions & 1 deletion packages/go_router_builder/lib/src/route_config.dart
Expand Up @@ -215,7 +215,10 @@ GoRoute get $_routeGetterName => ${_routeDefinition()};
String get _locationArgs {
final Iterable<String> pathItems = _parsedPath.map((Token e) {
if (e is ParameterToken) {
return '\${Uri.encodeComponent(${_encodeFor(e.name)})}';
// Enum types are encoded using a map, so we need a nullability check
// here to ensure it matches Uri.encodeComponent nullability
final DartType? type = _field(e.name)?.returnType;
return '\${Uri.encodeComponent(${_encodeFor(e.name)}${type?.isEnum ?? false ? '!' : ''})}';
}
if (e is PathToken) {
return e.value;
Expand Down

0 comments on commit 8d0ab2c

Please sign in to comment.