diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 7ba2b9ca9aa..ef1978e0527 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.4.0 + +- Adds `buildPageWithState` to `GoRouteData`. +- `GoRouteData.buildPage` is now deprecated in favor of `GoRouteData.buildPageWithState`. + ## 4.3.0 - Allows `Map` maps as `queryParams` of `goNamed`, `replacedName`, `pushNamed` and `namedLocation`. diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart index ec150858a00..4a2d4d4371b 100644 --- a/packages/go_router/lib/src/route_data.dart +++ b/packages/go_router/lib/src/route_data.dart @@ -12,7 +12,8 @@ import 'state.dart'; /// Baseclass for supporting /// [typed routing](https://gorouter.dev/typed-routing). /// -/// Subclasses must override one of [build], [buildPage], or [redirect]. +/// Subclasses must override one of [build], [buildPageWithState], or +/// [redirect]. abstract class GoRouteData { /// Allows subclasses to have `const` constructors. /// @@ -21,28 +22,50 @@ abstract class GoRouteData { /// Creates the [Widget] for `this` route. /// - /// Subclasses must override one of [build], [buildPage], or [redirect]. + /// Subclasses must override one of [build], [buildPageWithState], or + /// [redirect]. /// /// Corresponds to [GoRoute.builder]. Widget build(BuildContext context) => throw UnimplementedError( - 'One of `build` or `buildPage` must be implemented.', + 'One of `build` or `buildPageWithState` must be implemented.', ); /// A page builder for this route. /// /// Subclasses can override this function to provide a custom [Page]. /// - /// Subclasses must override one of [build], [buildPage], or [redirect]. + /// Subclasses must override one of [build], [buildPageWithState] or + /// [redirect]. /// /// Corresponds to [GoRoute.pageBuilder]. /// /// By default, returns a [Page] instance that is ignored, causing a default /// [Page] implementation to be used with the results of [build]. + @Deprecated( + 'This method has been deprecated in favor of buildPageWithState. ' + 'This feature was deprecated after v4.3.0.', + ) Page buildPage(BuildContext context) => const NoOpPage(); + /// A page builder for this route with [GoRouterState]. + /// + /// Subclasses can override this function to provide a custom [Page]. + /// + /// Subclasses must override one of [build], [buildPageWithState] or + /// [redirect]. + /// + /// Corresponds to [GoRoute.pageBuilder]. + /// + /// By default, returns a [Page] instance that is ignored, causing a default + /// [Page] implementation to be used with the results of [build]. + Page buildPageWithState(BuildContext context, GoRouterState state) => + // ignore: deprecated_member_use_from_same_package + buildPage(context); + /// An optional redirect function for this route. /// - /// Subclasses must override one of [build], [buildPage], or [redirect]. + /// Subclasses must override one of [build], [buildPageWithState], or + /// [redirect]. /// /// Corresponds to [GoRoute.redirect]. String? redirect() => null; @@ -83,7 +106,7 @@ abstract class GoRouteData { factoryImpl(state).build(context); Page pageBuilder(BuildContext context, GoRouterState state) => - factoryImpl(state).buildPage(context); + factoryImpl(state).buildPageWithState(context, state); String? redirect(GoRouterState state) => factoryImpl(state).redirect(); diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 5a72446104d..f93db6b1a67 100644 --- a/packages/go_router/pubspec.yaml +++ b/packages/go_router/pubspec.yaml @@ -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: 4.3.0 +version: 4.4.0 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 diff --git a/packages/go_router/test/route_data_test.dart b/packages/go_router/test/route_data_test.dart new file mode 100644 index 00000000000..4ae12f6dfb1 --- /dev/null +++ b/packages/go_router/test/route_data_test.dart @@ -0,0 +1,107 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; + +class _GoRouteDataBuild extends GoRouteData { + const _GoRouteDataBuild(); + @override + Widget build(BuildContext context) => const SizedBox(key: Key('build')); +} + +final GoRoute _goRouteDataBuild = GoRouteData.$route( + path: '/build', + factory: (GoRouterState state) => const _GoRouteDataBuild(), +); + +class _GoRouteDataBuildPage extends GoRouteData { + const _GoRouteDataBuildPage(); + @override + Page buildPage(BuildContext context) => const MaterialPage( + child: SizedBox(key: Key('buildPage')), + ); +} + +final GoRoute _goRouteDataBuildPage = GoRouteData.$route( + path: '/build-page', + factory: (GoRouterState state) => const _GoRouteDataBuildPage(), +); + +class _GoRouteDataBuildPageWithState extends GoRouteData { + const _GoRouteDataBuildPageWithState(); + @override + Page buildPageWithState(BuildContext context, GoRouterState state) => + const MaterialPage( + child: SizedBox(key: Key('buildPageWithState')), + ); +} + +final GoRoute _goRouteDataBuildPageWithState = GoRouteData.$route( + path: '/build-page-with-state', + factory: (GoRouterState state) => const _GoRouteDataBuildPageWithState(), +); + +final List _routes = [ + _goRouteDataBuild, + _goRouteDataBuildPage, + _goRouteDataBuildPageWithState, +]; + +void main() { + testWidgets( + 'It should build the page from the overridden build method', + (WidgetTester tester) async { + final GoRouter goRouter = GoRouter( + initialLocation: '/build', + routes: _routes, + ); + await tester.pumpWidget(MaterialApp.router( + routeInformationProvider: goRouter.routeInformationProvider, + routeInformationParser: goRouter.routeInformationParser, + routerDelegate: goRouter.routerDelegate, + )); + expect(find.byKey(const Key('build')), findsOneWidget); + expect(find.byKey(const Key('buildPage')), findsNothing); + expect(find.byKey(const Key('buildPageWithState')), findsNothing); + }, + ); + + testWidgets( + 'It should build the page from the overridden buildPage method', + (WidgetTester tester) async { + final GoRouter goRouter = GoRouter( + initialLocation: '/build-page', + routes: _routes, + ); + await tester.pumpWidget(MaterialApp.router( + routeInformationProvider: goRouter.routeInformationProvider, + routeInformationParser: goRouter.routeInformationParser, + routerDelegate: goRouter.routerDelegate, + )); + expect(find.byKey(const Key('build')), findsNothing); + expect(find.byKey(const Key('buildPage')), findsOneWidget); + expect(find.byKey(const Key('buildPageWithState')), findsNothing); + }, + ); + + testWidgets( + 'It should build the page from the overridden buildPageWithState method', + (WidgetTester tester) async { + final GoRouter goRouter = GoRouter( + initialLocation: '/build-page-with-state', + routes: _routes, + ); + await tester.pumpWidget(MaterialApp.router( + routeInformationProvider: goRouter.routeInformationProvider, + routeInformationParser: goRouter.routeInformationParser, + routerDelegate: goRouter.routerDelegate, + )); + expect(find.byKey(const Key('build')), findsNothing); + expect(find.byKey(const Key('buildPage')), findsNothing); + expect(find.byKey(const Key('buildPageWithState')), findsOneWidget); + }, + ); +}