Skip to content

Commit

Permalink
[go_router]: implemented helpers for ShellRoute (flutter#2730)
Browse files Browse the repository at this point in the history
* [Feature]: implemented helpers for ShellRoute

* [bugfix]: change export

* Removed named private constructor for TypedRoute

* Update CHANGELOG.md

* Update pubspec.yaml

* [Feature]: split routes per type

* [Feature]: add new exports

* Tests, refactor routes

* remove line in changelog

* Add navigatorKey for each route

* Fixed tests

* Format

* Bump version in pubspec.yaml

* Update packages/go_router/lib/src/route_data.dart

Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>

* Update packages/go_router/lib/src/route_data.dart

Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>

* Removed buildPageWithState tests

* Bump version in pubspec

* Address comments from code review

* Export ShellRouteData

* Remove unnecessary import

---------

Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>
Co-authored-by: John Ryan <ryjohn@google.com>
  • Loading branch information
3 people authored Feb 23, 2023
1 parent af5906b commit 5834b4c
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 59 deletions.
4 changes: 4 additions & 0 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.0.10

- Adds helpers for go_router_builder for ShellRoute support

## 6.0.9

- Fixes deprecation message for `GoRouterState.namedLocation`
Expand Down
3 changes: 2 additions & 1 deletion packages/go_router/lib/go_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export 'src/configuration.dart'
export 'src/misc/extensions.dart';
export 'src/misc/inherited_router.dart';
export 'src/pages/custom_transition_page.dart';
export 'src/route_data.dart' show GoRouteData, TypedGoRoute;
export 'src/route_data.dart'
show GoRouteData, TypedGoRoute, TypedShellRoute, ShellRouteData;
export 'src/router.dart';
export 'src/typedefs.dart'
show GoRouterPageBuilder, GoRouterRedirect, GoRouterWidgetBuilder;
138 changes: 129 additions & 9 deletions packages/go_router/lib/src/route_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import 'package:meta/meta_meta.dart';
import 'route.dart';
import 'state.dart';

/// A superclass for each route data
abstract class RouteData {
/// Default const constructor
const RouteData();
}

/// Baseclass for supporting
/// [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html).
///
/// Subclasses must override one of [build], [buildPage], or
/// [redirect].
/// {@category Type-safe routes}
abstract class GoRouteData {
abstract class GoRouteData extends RouteData {
/// Allows subclasses to have `const` constructors.
///
/// [GoRouteData] is abstract and cannot be instantiated directly.
Expand Down Expand Up @@ -74,7 +80,8 @@ abstract class GoRouteData {
static GoRoute $route<T extends GoRouteData>({
required String path,
required T Function(GoRouterState) factory,
List<GoRoute> routes = const <GoRoute>[],
GlobalKey<NavigatorState>? parentNavigatorKey,
List<RouteBase> routes = const <RouteBase>[],
}) {
T factoryImpl(GoRouterState state) {
final Object? extra = state.extra;
Expand Down Expand Up @@ -103,6 +110,7 @@ abstract class GoRouteData {
pageBuilder: pageBuilder,
redirect: redirect,
routes: routes,
parentNavigatorKey: parentNavigatorKey,
);
}

Expand All @@ -111,26 +119,138 @@ abstract class GoRouteData {
static final Expando<GoRouteData> _stateObjectExpando = Expando<GoRouteData>(
'GoRouteState to GoRouteData expando',
);

/// [navigatorKey] is used to point to a certain navigator
///
/// It will use the given key to find the right navigator for [GoRoute]
GlobalKey<NavigatorState>? get navigatorKey => null;
}

/// Annotation for types that support typed routing.
/// Base class for supporting
/// [nested navigation](https://pub.dev/packages/go_router#nested-navigation)
abstract class ShellRouteData extends RouteData {
/// Default const constructor
const ShellRouteData();

/// [pageBuilder] is used to build the page
Page<void> pageBuilder(
BuildContext context,
GoRouterState state,
Widget navigator,
) =>
const NoOpPage();

/// [pageBuilder] is used to build the page
Widget builder(
BuildContext context,
GoRouterState state,
Widget navigator,
) =>
throw UnimplementedError(
'One of `builder` or `pageBuilder` must be implemented.',
);

/// A helper function used by generated code.
///
/// Should not be used directly.
static ShellRoute $route<T extends ShellRouteData>({
required T Function(GoRouterState) factory,
GlobalKey<NavigatorState>? navigatorKey,
List<RouteBase> routes = const <RouteBase>[],
}) {
T factoryImpl(GoRouterState state) {
final Object? extra = state.extra;

// If the "extra" value is of type `T` then we know it's the source
// instance of `GoRouteData`, so it doesn't need to be recreated.
if (extra is T) {
return extra;
}

return (_stateObjectExpando[state] ??= factory(state)) as T;
}

Widget builder(
BuildContext context,
GoRouterState state,
Widget navigator,
) =>
factoryImpl(state).builder(
context,
state,
navigator,
);

Page<void> pageBuilder(
BuildContext context,
GoRouterState state,
Widget navigator,
) =>
factoryImpl(state).pageBuilder(
context,
state,
navigator,
);

return ShellRoute(
builder: builder,
pageBuilder: pageBuilder,
routes: routes,
navigatorKey: navigatorKey,
);
}

/// Used to cache [ShellRouteData] that corresponds to a given [GoRouterState]
/// to minimize the number of times it has to be deserialized.
static final Expando<ShellRouteData> _stateObjectExpando =
Expando<ShellRouteData>(
'GoRouteState to ShellRouteData expando',
);

/// It will be used to instantiate [Navigator] with the given key
GlobalKey<NavigatorState>? get navigatorKey => null;
}

/// A superclass for each typed route descendant
class TypedRoute<T extends RouteData> {
/// Default const constructor
const TypedRoute();
}

/// A superclass for each typed go route descendant
@Target(<TargetKind>{TargetKind.library, TargetKind.classType})
class TypedGoRoute<T extends GoRouteData> {
/// Instantiates a new instance of [TypedGoRoute].
class TypedGoRoute<T extends GoRouteData> extends TypedRoute<T> {
/// Default const constructor
const TypedGoRoute({
required this.path,
this.routes = const <TypedGoRoute<GoRouteData>>[],
this.routes = const <TypedRoute<RouteData>>[],
});

/// The path that corresponds to this rout.
/// The path that corresponds to this route.
///
/// See [GoRoute.path].
///
///
final String path;

/// Child route definitions.
///
/// See [GoRoute.routes].
final List<TypedGoRoute<GoRouteData>> routes;
/// See [RouteBase.routes].
final List<TypedRoute<RouteData>> routes;
}

/// A superclass for each typed shell route descendant
@Target(<TargetKind>{TargetKind.library, TargetKind.classType})
class TypedShellRoute<T extends ShellRouteData> extends TypedRoute<T> {
/// Default const constructor
const TypedShellRoute({
this.routes = const <TypedRoute<RouteData>>[],
});

/// Child route definitions.
///
/// See [RouteBase.routes].
final List<TypedRoute<RouteData>> routes;
}

/// Internal class used to signal that the default page behavior should be used.
Expand Down
2 changes: 1 addition & 1 deletion packages/go_router/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: go_router
description: A declarative router for Flutter based on Navigation 2 supporting
deep linking, data-driven routes and more
version: 6.0.9
version: 6.0.10
repository: https://github.com/flutter/packages/tree/main/packages/go_router
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22

Expand Down
Loading

0 comments on commit 5834b4c

Please sign in to comment.