diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index da0e1f2cd935..a7414a840e50 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.2 + +* Supports returning value in generated `push` method. [go_router CHANGELOG](https://github.com/flutter/packages/blob/main/packages/go_router/CHANGELOG.md#650) + ## 1.2.1 * Supports opt-in required extra parameters. [#117261](https://github.com/flutter/flutter/issues/117261) diff --git a/packages/go_router_builder/README.md b/packages/go_router_builder/README.md index e911d33be5c4..6632625afc8d 100644 --- a/packages/go_router_builder/README.md +++ b/packages/go_router_builder/README.md @@ -165,6 +165,17 @@ void _tap() => PersonRoute(pid: 'p1').go(context); This is the point of typed routing: the error is found statically. +## Return value + +Starting from `go_router` 6.5.0, pushing a route and subsequently popping it, can produce +a return value. The generated routes also follow this functionality. + +```dart +void _tap() async { + final result = await PersonRoute(pid: 'p1').go(context); +} +``` + ## Query parameters Optional parameters (named or positional) indicate query parameters: diff --git a/packages/go_router_builder/example/lib/all_types.g.dart b/packages/go_router_builder/example/lib/all_types.g.dart index 0dc37d5e5339..7cf692f6cbe7 100644 --- a/packages/go_router_builder/example/lib/all_types.g.dart +++ b/packages/go_router_builder/example/lib/all_types.g.dart @@ -81,7 +81,7 @@ extension $AllTypesBaseRouteExtension on AllTypesBaseRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -103,7 +103,7 @@ extension $BigIntRouteExtension on BigIntRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -133,7 +133,7 @@ extension $BoolRouteExtension on BoolRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -157,7 +157,7 @@ extension $DateTimeRouteExtension on DateTimeRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -187,7 +187,7 @@ extension $DoubleRouteExtension on DoubleRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -213,7 +213,7 @@ extension $IntRouteExtension on IntRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -239,7 +239,7 @@ extension $NumRouteExtension on NumRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -271,7 +271,7 @@ extension $EnumRouteExtension on EnumRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -303,7 +303,7 @@ extension $EnhancedEnumRouteExtension on EnhancedEnumRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -329,7 +329,7 @@ extension $StringRouteExtension on StringRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -350,7 +350,7 @@ extension $UriRouteExtension on UriRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -466,7 +466,7 @@ extension $IterableRouteExtension on IterableRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -580,7 +580,7 @@ extension $IterableRouteWithDefaultValuesExtension void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/lib/extra_example.g.dart b/packages/go_router_builder/example/lib/extra_example.g.dart index b9febb44e7a7..1a090c3a42b3 100644 --- a/packages/go_router_builder/example/lib/extra_example.g.dart +++ b/packages/go_router_builder/example/lib/extra_example.g.dart @@ -31,7 +31,8 @@ extension $RequiredExtraRouteExtension on RequiredExtraRoute { void go(BuildContext context) => context.go(location, extra: $extra); - void push(BuildContext context) => context.push(location, extra: $extra); + Future push(BuildContext context) => + context.push(location, extra: $extra); void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: $extra); @@ -54,7 +55,8 @@ extension $OptionalExtraRouteExtension on OptionalExtraRoute { void go(BuildContext context) => context.go(location, extra: $extra); - void push(BuildContext context) => context.push(location, extra: $extra); + Future push(BuildContext context) => + context.push(location, extra: $extra); void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: $extra); @@ -74,7 +76,7 @@ extension $SplashRouteExtension on SplashRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/lib/main.dart b/packages/go_router_builder/example/lib/main.dart index f6a64edf1842..cf917c59b5ce 100644 --- a/packages/go_router_builder/example/lib/main.dart +++ b/packages/go_router_builder/example/lib/main.dart @@ -76,7 +76,8 @@ class App extends StatelessWidget { ], ), ], - ) + ), + TypedGoRoute(path: 'family-count/:count'), ], ) class HomeRoute extends GoRouteData { @@ -149,6 +150,17 @@ class PersonDetailsRoute extends GoRouteData { } } +class FamilyCountRoute extends GoRouteData { + const FamilyCountRoute(this.count); + + final int count; + + @override + Widget build(BuildContext context, GoRouterState state) => FamilyCountScreen( + count: count, + ); +} + class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @@ -161,14 +173,38 @@ class HomeScreen extends StatelessWidget { title: const Text(App.title), centerTitle: true, actions: [ - ElevatedButton( - onPressed: () => const PersonRoute('f1', 1).push(context), - child: const Text('Push a route'), - ), - IconButton( - onPressed: info.logout, - tooltip: 'Logout: ${info.userName}', - icon: const Icon(Icons.logout), + PopupMenuButton( + itemBuilder: (BuildContext context) { + return >[ + PopupMenuItem( + value: '1', + child: const Text('Push w/o return value'), + onTap: () => const PersonRoute('f1', 1).push(context), + ), + PopupMenuItem( + value: '2', + child: const Text('Push w/ return value'), + onTap: () async { + FamilyCountRoute(familyData.length) + .push(context) + .then((int? value) { + if (value != null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Age was: $value'), + ), + ); + } + }); + }, + ), + PopupMenuItem( + value: '3', + child: Text('Logout: ${info.userName}'), + onTap: () => info.logout(), + ), + ]; + }, ), ], ), @@ -277,6 +313,35 @@ class PersonDetailsPage extends StatelessWidget { ); } +class FamilyCountScreen extends StatelessWidget { + const FamilyCountScreen({super.key, required this.count}); + + final int count; + + @override + Widget build(BuildContext context) => Scaffold( + appBar: AppBar(title: const Text('Family Count')), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + 'There are $count families', + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + ElevatedButton( + onPressed: () => context.pop(count), + child: Text('Pop with return value $count'), + ), + ], + ), + ), + ); +} + class LoginScreen extends StatelessWidget { const LoginScreen({this.from, super.key}); final String? from; diff --git a/packages/go_router_builder/example/lib/main.g.dart b/packages/go_router_builder/example/lib/main.g.dart index ba15ccd83f7b..864e8e121ef8 100644 --- a/packages/go_router_builder/example/lib/main.g.dart +++ b/packages/go_router_builder/example/lib/main.g.dart @@ -33,6 +33,10 @@ RouteBase get $homeRoute => GoRouteData.$route( ), ], ), + GoRouteData.$route( + path: 'family-count/:count', + factory: $FamilyCountRouteExtension._fromState, + ), ], ); @@ -45,7 +49,7 @@ extension $HomeRouteExtension on HomeRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -62,7 +66,7 @@ extension $FamilyRouteExtension on FamilyRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -80,7 +84,7 @@ extension $PersonRouteExtension on PersonRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -101,12 +105,30 @@ extension $PersonDetailsRouteExtension on PersonDetailsRoute { void go(BuildContext context) => context.go(location, extra: $extra); - void push(BuildContext context) => context.push(location, extra: $extra); + Future push(BuildContext context) => + context.push(location, extra: $extra); void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: $extra); } +extension $FamilyCountRouteExtension on FamilyCountRoute { + static FamilyCountRoute _fromState(GoRouterState state) => FamilyCountRoute( + int.parse(state.params['count']!), + ); + + String get location => GoRouteData.$location( + '/family-count/${Uri.encodeComponent(count.toString())}', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); +} + const _$PersonDetailsEnumMap = { PersonDetails.hobbies: 'hobbies', PersonDetails.favoriteFood: 'favorite-food', @@ -137,7 +159,7 @@ extension $LoginRouteExtension on LoginRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/lib/shell_route_example.g.dart b/packages/go_router_builder/example/lib/shell_route_example.g.dart index 531502515a05..e3544c7320ff 100644 --- a/packages/go_router_builder/example/lib/shell_route_example.g.dart +++ b/packages/go_router_builder/example/lib/shell_route_example.g.dart @@ -27,7 +27,7 @@ extension $LoginRouteExtension on LoginRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -61,7 +61,7 @@ extension $FooRouteDataExtension on FooRouteData { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -76,7 +76,7 @@ extension $BarRouteDataExtension on BarRouteData { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart b/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart index 523af4e98935..a8a51017e33b 100644 --- a/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart +++ b/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart @@ -48,7 +48,7 @@ extension $HomeRouteDataExtension on HomeRouteData { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -64,7 +64,7 @@ extension $UsersRouteDataExtension on UsersRouteData { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -81,7 +81,7 @@ extension $UserRouteDataExtension on UserRouteData { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/lib/simple_example.g.dart b/packages/go_router_builder/example/lib/simple_example.g.dart index 4edd92ae6e1d..16538ef16225 100644 --- a/packages/go_router_builder/example/lib/simple_example.g.dart +++ b/packages/go_router_builder/example/lib/simple_example.g.dart @@ -32,7 +32,7 @@ extension $HomeRouteExtension on HomeRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -49,7 +49,7 @@ extension $FamilyRouteExtension on FamilyRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); diff --git a/packages/go_router_builder/example/test/widget_test.dart b/packages/go_router_builder/example/test/widget_test.dart index aa6061a42b49..e53f9123c763 100644 --- a/packages/go_router_builder/example/test/widget_test.dart +++ b/packages/go_router_builder/example/test/widget_test.dart @@ -2,6 +2,7 @@ // 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_builder_example/main.dart'; @@ -12,13 +13,24 @@ void main() { await tester.tap(find.text('Login')); await tester.pumpAndSettle(); - await tester.tap(find.text('Push a route')); + await _openPopupMenu(tester); + + await tester.tap(find.text('Push w/o return value')); await tester.pumpAndSettle(); expect(find.text('Chris'), findsOneWidget); await tester.pageBack(); await tester.pumpAndSettle(); + await _openPopupMenu(tester); + + await tester.tap(find.text('Push w/ return value')); + await tester.pumpAndSettle(); + expect(find.text('Family Count'), findsOneWidget); + + await tester.pageBack(); + await tester.pumpAndSettle(); + await tester.tap(find.text('Sells')); await tester.pumpAndSettle(); @@ -39,3 +51,11 @@ void main() { expect(find.text('Extra click count: 1'), findsOneWidget); }); } + +Future _openPopupMenu(WidgetTester tester) async { + final Finder moreButton = find.byIcon(Icons.more_vert); + expect(moreButton, findsOneWidget); + + await tester.tap(moreButton); + await tester.pumpAndSettle(); +} diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index c0d1ace5476c..c45a9407a79b 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -207,8 +207,8 @@ extension $_extensionName on $_className { void go(BuildContext context) => context.go(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); - void push(BuildContext context) => - context.push(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); + Future push(BuildContext context) => + context.push(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); void pushReplacement(BuildContext context) => context.pushReplacement(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index fe1af19562bd..11726b6ebcc7 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -2,7 +2,7 @@ name: go_router_builder description: >- A builder that supports generated strongly-typed route helpers for package:go_router -version: 1.2.1 +version: 1.2.2 repository: https://github.com/flutter/packages/tree/main/packages/go_router_builder issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22 diff --git a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart index 4a8a095ac40b..1e39c205ef6c 100644 --- a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart +++ b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart @@ -79,7 +79,7 @@ extension $EnumParamExtension on EnumParam { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -131,7 +131,7 @@ extension $DefaultValueRouteExtension on DefaultValueRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -173,7 +173,8 @@ extension $ExtraValueRouteExtension on ExtraValueRoute { void go(BuildContext context) => context.go(location, extra: $extra); - void push(BuildContext context) => context.push(location, extra: $extra); + Future push(BuildContext context) => + context.push(location, extra: $extra); void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: $extra); @@ -213,7 +214,8 @@ extension $RequiredExtraValueRouteExtension on RequiredExtraValueRoute { void go(BuildContext context) => context.go(location, extra: $extra); - void push(BuildContext context) => context.push(location, extra: $extra); + Future push(BuildContext context) => + context.push(location, extra: $extra); void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: $extra); @@ -259,7 +261,7 @@ extension $IterableWithEnumRouteExtension on IterableWithEnumRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location); @@ -312,7 +314,7 @@ extension $IterableDefaultValueRouteExtension on IterableDefaultValueRoute { void go(BuildContext context) => context.go(location); - void push(BuildContext context) => context.push(location); + Future push(BuildContext context) => context.push(location); void pushReplacement(BuildContext context) => context.pushReplacement(location);