From 37be48ced68d4629ca86dfe59260e6106583675f Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 29 May 2024 15:12:19 +0700 Subject: [PATCH 01/26] - Adds `GoRouter.goRelative` - Adds `TypedRelativeGoRoute` --- .../lib/src/information_provider.dart | 27 ++ .../go_router/lib/src/misc/extensions.dart | 7 + packages/go_router/lib/src/route_data.dart | 22 ++ packages/go_router/lib/src/router.dart | 9 + packages/go_router/test/go_router_test.dart | 277 ++++++++++++++++++ 5 files changed, 342 insertions(+) diff --git a/packages/go_router/lib/src/information_provider.dart b/packages/go_router/lib/src/information_provider.dart index dc979193b32..999cd530a25 100644 --- a/packages/go_router/lib/src/information_provider.dart +++ b/packages/go_router/lib/src/information_provider.dart @@ -172,6 +172,33 @@ class GoRouteInformationProvider extends RouteInformationProvider ); } + /// Relatively go to [relativeLocation]. + void goRelative(String relativeLocation, {Object? extra}) { + assert( + !relativeLocation.startsWith('/'), + "Relative locations must not start with a '/'.", + ); + + final Uri currentUri = value.uri; + Uri newUri = Uri.parse( + currentUri.path.endsWith('/') + ? '${currentUri.path}$relativeLocation' + : '${currentUri.path}/$relativeLocation', + ); + newUri = newUri.replace(queryParameters: { + ...currentUri.queryParameters, + ...newUri.queryParameters, + }); + + _setValue( + newUri.toString(), + RouteInformationState( + extra: extra, + type: NavigatingType.go, + ), + ); + } + /// Restores the current route matches with the `matchList`. void restore(String location, {required RouteMatchList matchList}) { _setValue( diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart index c137022b802..f5f654ce475 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -24,6 +24,13 @@ extension GoRouterHelper on BuildContext { void go(String location, {Object? extra}) => GoRouter.of(this).go(location, extra: extra); + /// Navigate relative to a location. + void goRelative(String location, {Object? extra}) => + GoRouter.of(this).goRelative( + location, + extra: extra, + ); + /// Navigate to a named route. void goNamed( String name, { diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart index afe6159cecb..c6c2e13845b 100644 --- a/packages/go_router/lib/src/route_data.dart +++ b/packages/go_router/lib/src/route_data.dart @@ -390,6 +390,28 @@ class TypedGoRoute extends TypedRoute { final List> routes; } +/// A superclass for each typed go route descendant +@Target({TargetKind.library, TargetKind.classType}) +class TypedRelativeGoRoute extends TypedRoute { + /// Default const constructor + const TypedRelativeGoRoute({ + required this.path, + this.routes = const >[], + }); + + /// The relative path that corresponds to this route. + /// + /// See [GoRoute.path]. + /// + /// + final String path; + + /// Child route definitions. + /// + /// See [RouteBase.routes]. + final List> routes; +} + /// A superclass for each typed shell route descendant @Target({TargetKind.library, TargetKind.classType}) class TypedShellRoute extends TypedRoute { diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index dc6d88057eb..0146a1ca29c 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -340,6 +340,15 @@ class GoRouter implements RouterConfig { routeInformationProvider.go(location, extra: extra); } + /// Navigate to a URI location by appending [relativeLocation] to the current [GoRouterState.matchedLocation] w/ optional query parameters, e.g. + void goRelative( + String relativeLocation, { + Object? extra, + }) { + log('going relative to $relativeLocation'); + routeInformationProvider.goRelative(relativeLocation, extra: extra); + } + /// Restore the RouteMatchList void restore(RouteMatchList matchList) { log('restoring ${matchList.uri}'); diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index f395faf906f..3598bfe2ade 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -1791,6 +1791,283 @@ void main() { }); }); + group('go relative', () { + testWidgets('from default route', (WidgetTester tester) async { + final List routes = [ + GoRoute( + path: '/', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'login', + builder: (BuildContext context, GoRouterState state) => + const LoginScreen(), + ), + ], + ), + ]; + + final GoRouter router = await createRouter(routes, tester); + router.goRelative('login'); + await tester.pumpAndSettle(); + expect(find.byType(LoginScreen), findsOneWidget); + }); + + testWidgets('from non-default route', (WidgetTester tester) async { + final List routes = [ + GoRoute( + path: '/home', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'login', + builder: (BuildContext context, GoRouterState state) => + const LoginScreen(), + ), + ], + ), + ]; + + final GoRouter router = await createRouter(routes, tester); + router.go('/home'); + router.goRelative('login'); + await tester.pumpAndSettle(); + expect(find.byType(LoginScreen), findsOneWidget); + }); + + testWidgets('match w/ path params', (WidgetTester tester) async { + const String fid = 'f2'; + const String pid = 'p1'; + + final List routes = [ + GoRoute( + path: '/home', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'family/:fid', + builder: (BuildContext context, GoRouterState state) => + const FamilyScreen('dummy'), + routes: [ + GoRoute( + name: 'person', + path: 'person/:pid', + builder: (BuildContext context, GoRouterState state) { + expect(state.pathParameters, + {'fid': fid, 'pid': pid}); + return const PersonScreen('dummy', 'dummy'); + }, + ), + ], + ), + ], + ), + ]; + + final GoRouter router = + await createRouter(routes, tester, initialLocation: '/home'); + router.go('/'); + + router.goRelative('family/$fid'); + await tester.pumpAndSettle(); + expect(find.byType(FamilyScreen), findsOneWidget); + + router.goRelative('person/$pid'); + await tester.pumpAndSettle(); + expect(find.byType(PersonScreen), findsOneWidget); + }); + + testWidgets('match w/ query params', (WidgetTester tester) async { + const String fid = 'f2'; + const String pid = 'p1'; + + final List routes = [ + GoRoute( + path: '/home', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'family', + builder: (BuildContext context, GoRouterState state) => + const FamilyScreen('dummy'), + routes: [ + GoRoute( + path: 'person', + builder: (BuildContext context, GoRouterState state) { + expect(state.uri.queryParameters, + {'fid': fid, 'pid': pid}); + return const PersonScreen('dummy', 'dummy'); + }, + ), + ], + ), + ], + ), + ]; + + final GoRouter router = + await createRouter(routes, tester, initialLocation: '/home'); + + router.goRelative('family?fid=$fid'); + await tester.pumpAndSettle(); + expect(find.byType(FamilyScreen), findsOneWidget); + + router.goRelative('person?pid=$pid'); + await tester.pumpAndSettle(); + expect(find.byType(PersonScreen), findsOneWidget); + }); + + testWidgets('too few params', (WidgetTester tester) async { + const String pid = 'p1'; + + final List routes = [ + GoRoute( + path: '/home', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'family/:fid', + builder: (BuildContext context, GoRouterState state) => + const FamilyScreen('dummy'), + routes: [ + GoRoute( + path: 'person/:pid', + builder: (BuildContext context, GoRouterState state) => + const PersonScreen('dummy', 'dummy'), + ), + ], + ), + ], + ), + ]; + // await expectLater(() async { + final GoRouter router = await createRouter( + routes, + tester, + initialLocation: '/home', + errorBuilder: (BuildContext context, GoRouterState state) => + TestErrorScreen(state.error!), + ); + router.goRelative('family/person/$pid'); + await tester.pumpAndSettle(); + expect(find.byType(TestErrorScreen), findsOneWidget); + + final List matches = + router.routerDelegate.currentConfiguration.matches; + expect(matches, hasLength(0)); + }); + + testWidgets('match no route', (WidgetTester tester) async { + final List routes = [ + GoRoute( + path: '/home', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen(), + routes: [ + GoRoute( + path: 'family', + builder: (BuildContext context, GoRouterState state) => + const FamilyScreen('dummy'), + routes: [ + GoRoute( + path: 'person', + builder: (BuildContext context, GoRouterState state) => + const PersonScreen('dummy', 'dummy'), + ), + ], + ), + ], + ), + ]; + + final GoRouter router = await createRouter( + routes, + tester, + initialLocation: '/home', + errorBuilder: (BuildContext context, GoRouterState state) => + TestErrorScreen(state.error!), + ); + router.go('person'); + + await tester.pumpAndSettle(); + expect(find.byType(TestErrorScreen), findsOneWidget); + + final List matches = + router.routerDelegate.currentConfiguration.matches; + expect(matches, hasLength(0)); + }); + + testWidgets('preserve path param spaces and slashes', + (WidgetTester tester) async { + const String param1 = 'param w/ spaces and slashes'; + final List routes = [ + GoRoute( + path: '/home', + builder: dummy, + routes: [ + GoRoute( + path: 'page1/:param1', + builder: (BuildContext c, GoRouterState s) { + expect(s.pathParameters['param1'], param1); + return const DummyScreen(); + }, + ), + ], + ) + ]; + + final GoRouter router = + await createRouter(routes, tester, initialLocation: '/home'); + final String loc = 'page1/${Uri.encodeComponent(param1)}'; + router.goRelative(loc); + + await tester.pumpAndSettle(); + expect(find.byType(DummyScreen), findsOneWidget); + + final RouteMatchList matches = router.routerDelegate.currentConfiguration; + expect(matches.pathParameters['param1'], param1); + }); + + testWidgets('preserve query param spaces and slashes', + (WidgetTester tester) async { + const String param1 = 'param w/ spaces and slashes'; + final List routes = [ + GoRoute( + path: '/home', + builder: dummy, + routes: [ + GoRoute( + path: 'page1', + builder: (BuildContext c, GoRouterState s) { + expect(s.uri.queryParameters['param1'], param1); + return const DummyScreen(); + }, + ), + ], + ) + ]; + + final GoRouter router = + await createRouter(routes, tester, initialLocation: '/home'); + + router.goRelative(Uri( + path: 'page1', + queryParameters: {'param1': param1}, + ).toString()); + + await tester.pumpAndSettle(); + expect(find.byType(DummyScreen), findsOneWidget); + + final RouteMatchList matches = router.routerDelegate.currentConfiguration; + expect(matches.uri.queryParameters['param1'], param1); + }); + }); + group('redirects', () { testWidgets('top-level redirect', (WidgetTester tester) async { final List routes = [ From f8061ce550d14d2a83e1fc5238c73fbc1ec2917d Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 29 May 2024 15:27:23 +0700 Subject: [PATCH 02/26] add go_relative example for go_router --- .../go_router/example/lib/go_relative.dart | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 packages/go_router/example/lib/go_relative.dart diff --git a/packages/go_router/example/lib/go_relative.dart b/packages/go_router/example/lib/go_relative.dart new file mode 100644 index 00000000000..114e3b2fdff --- /dev/null +++ b/packages/go_router/example/lib/go_relative.dart @@ -0,0 +1,120 @@ +// 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:go_router/go_router.dart'; + +/// This sample app demonstrates how to use GoRoute.goRelative. +void main() => runApp(const MyApp()); + +/// The route configuration. +final GoRouter _router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (BuildContext context, GoRouterState state) { + return const HomeScreen(); + }, + routes: [ + GoRoute( + path: 'details', + builder: (BuildContext context, GoRouterState state) { + return const DetailsScreen(); + }, + routes: [ + GoRoute( + path: 'settings', + builder: (BuildContext context, GoRouterState state) { + return const SettingsScreen(); + }, + ), + ], + ), + ], + ), + ], +); + +/// The main app. +class MyApp extends StatelessWidget { + /// Constructs a [MyApp] + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + routerConfig: _router, + ); + } +} + +/// The home screen +class HomeScreen extends StatelessWidget { + /// Constructs a [HomeScreen] + const HomeScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Home Screen')), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () => context.goRelative('details'), + child: const Text('Go to the Details screen'), + ), + ], + ), + ), + ); + } +} + +/// The details screen +class DetailsScreen extends StatelessWidget { + /// Constructs a [DetailsScreen] + const DetailsScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Details Screen')), + body: Center( + child: Column( + children: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: const Text('go back'), + ), + TextButton( + onPressed: () { + context.goRelative('settings'); + }, + child: const Text('go to settings'), + ), + ], + )), + ); + } +} + +/// The settings screen +class SettingsScreen extends StatelessWidget { + /// Constructs a [SettingsScreen] + const SettingsScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Settings Screen')), + body: const Center( + child: Text('Settings'), + ), + ); + } +} From 8a771474c327d8e5f8b7b04a0df106729a439ecb Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 29 May 2024 15:32:11 +0700 Subject: [PATCH 03/26] add go_relative_test for the example --- .../go_router/example/lib/go_relative.dart | 2 +- .../example/test/go_relative_test.dart | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 packages/go_router/example/test/go_relative_test.dart diff --git a/packages/go_router/example/lib/go_relative.dart b/packages/go_router/example/lib/go_relative.dart index 114e3b2fdff..20f42dbb6ef 100644 --- a/packages/go_router/example/lib/go_relative.dart +++ b/packages/go_router/example/lib/go_relative.dart @@ -95,7 +95,7 @@ class DetailsScreen extends StatelessWidget { onPressed: () { context.goRelative('settings'); }, - child: const Text('go to settings'), + child: const Text('Go to the Settings screen'), ), ], )), diff --git a/packages/go_router/example/test/go_relative_test.dart b/packages/go_router/example/test/go_relative_test.dart new file mode 100644 index 00000000000..fbc884d5559 --- /dev/null +++ b/packages/go_router/example/test/go_relative_test.dart @@ -0,0 +1,21 @@ +// 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_test/flutter_test.dart'; +import 'package:go_router_examples/go_relative.dart' as example; + +void main() { + testWidgets('example works', (WidgetTester tester) async { + await tester.pumpWidget(const example.MyApp()); + expect(find.byType(example.HomeScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Details screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.DetailsScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Settings screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.SettingsScreen), findsOneWidget); + }); +} From 61127f335bd325e62230a13393b6ca7ebb29296b Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 29 May 2024 17:11:09 +0700 Subject: [PATCH 04/26] fix failed test --- packages/go_router/test/go_router_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index 3598bfe2ade..23b99452fbf 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -1869,7 +1869,6 @@ void main() { final GoRouter router = await createRouter(routes, tester, initialLocation: '/home'); - router.go('/'); router.goRelative('family/$fid'); await tester.pumpAndSettle(); From 687b332e135c3044b73edecad09fcc971acf3fec Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 19 Jun 2024 19:45:39 +0700 Subject: [PATCH 05/26] replace goRelative with go('./$path') --- .../go_router/example/lib/go_relative.dart | 4 ++-- .../lib/src/information_provider.dart | 10 +++++++-- .../go_router/lib/src/misc/extensions.dart | 7 ------- packages/go_router/lib/src/router.dart | 9 -------- packages/go_router/test/go_router_test.dart | 21 ++++++++++--------- 5 files changed, 21 insertions(+), 30 deletions(-) diff --git a/packages/go_router/example/lib/go_relative.dart b/packages/go_router/example/lib/go_relative.dart index 20f42dbb6ef..54f17293d2f 100644 --- a/packages/go_router/example/lib/go_relative.dart +++ b/packages/go_router/example/lib/go_relative.dart @@ -63,7 +63,7 @@ class HomeScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( - onPressed: () => context.goRelative('details'), + onPressed: () => context.go('./details'), child: const Text('Go to the Details screen'), ), ], @@ -93,7 +93,7 @@ class DetailsScreen extends StatelessWidget { ), TextButton( onPressed: () { - context.goRelative('settings'); + context.go('./settings'); }, child: const Text('Go to the Settings screen'), ), diff --git a/packages/go_router/lib/src/information_provider.dart b/packages/go_router/lib/src/information_provider.dart index 999cd530a25..6588d07e35d 100644 --- a/packages/go_router/lib/src/information_provider.dart +++ b/packages/go_router/lib/src/information_provider.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'match.dart'; +import 'path_utils.dart'; /// The type of the navigation. /// @@ -135,11 +136,16 @@ class GoRouteInformationProvider extends RouteInformationProvider } void _setValue(String location, Object state) { - final Uri uri = Uri.parse(location); + Uri uri = Uri.parse(location); + + // Check for relative location + if (location.startsWith('./')) { + uri = concatenateUris(_value.uri, uri); + } final bool shouldNotify = _valueHasChanged(newLocationUri: uri, newState: state); - _value = RouteInformation(uri: Uri.parse(location), state: state); + _value = RouteInformation(uri: uri, state: state); if (shouldNotify) { notifyListeners(); } diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart index f5f654ce475..c137022b802 100644 --- a/packages/go_router/lib/src/misc/extensions.dart +++ b/packages/go_router/lib/src/misc/extensions.dart @@ -24,13 +24,6 @@ extension GoRouterHelper on BuildContext { void go(String location, {Object? extra}) => GoRouter.of(this).go(location, extra: extra); - /// Navigate relative to a location. - void goRelative(String location, {Object? extra}) => - GoRouter.of(this).goRelative( - location, - extra: extra, - ); - /// Navigate to a named route. void goNamed( String name, { diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index 0146a1ca29c..dc6d88057eb 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -340,15 +340,6 @@ class GoRouter implements RouterConfig { routeInformationProvider.go(location, extra: extra); } - /// Navigate to a URI location by appending [relativeLocation] to the current [GoRouterState.matchedLocation] w/ optional query parameters, e.g. - void goRelative( - String relativeLocation, { - Object? extra, - }) { - log('going relative to $relativeLocation'); - routeInformationProvider.goRelative(relativeLocation, extra: extra); - } - /// Restore the RouteMatchList void restore(RouteMatchList matchList) { log('restoring ${matchList.uri}'); diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index 23b99452fbf..d8a6316faec 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -1809,7 +1809,7 @@ void main() { ]; final GoRouter router = await createRouter(routes, tester); - router.goRelative('login'); + router.go('./login'); await tester.pumpAndSettle(); expect(find.byType(LoginScreen), findsOneWidget); }); @@ -1832,7 +1832,7 @@ void main() { final GoRouter router = await createRouter(routes, tester); router.go('/home'); - router.goRelative('login'); + router.go('./login'); await tester.pumpAndSettle(); expect(find.byType(LoginScreen), findsOneWidget); }); @@ -1870,11 +1870,11 @@ void main() { final GoRouter router = await createRouter(routes, tester, initialLocation: '/home'); - router.goRelative('family/$fid'); + router.go('./family/$fid'); await tester.pumpAndSettle(); expect(find.byType(FamilyScreen), findsOneWidget); - router.goRelative('person/$pid'); + router.go('./person/$pid'); await tester.pumpAndSettle(); expect(find.byType(PersonScreen), findsOneWidget); }); @@ -1911,11 +1911,11 @@ void main() { final GoRouter router = await createRouter(routes, tester, initialLocation: '/home'); - router.goRelative('family?fid=$fid'); + router.go('./family?fid=$fid'); await tester.pumpAndSettle(); expect(find.byType(FamilyScreen), findsOneWidget); - router.goRelative('person?pid=$pid'); + router.go('./person?pid=$pid'); await tester.pumpAndSettle(); expect(find.byType(PersonScreen), findsOneWidget); }); @@ -1952,7 +1952,7 @@ void main() { errorBuilder: (BuildContext context, GoRouterState state) => TestErrorScreen(state.error!), ); - router.goRelative('family/person/$pid'); + router.go('./family/person/$pid'); await tester.pumpAndSettle(); expect(find.byType(TestErrorScreen), findsOneWidget); @@ -2023,7 +2023,7 @@ void main() { final GoRouter router = await createRouter(routes, tester, initialLocation: '/home'); final String loc = 'page1/${Uri.encodeComponent(param1)}'; - router.goRelative(loc); + router.go('./$loc'); await tester.pumpAndSettle(); expect(find.byType(DummyScreen), findsOneWidget); @@ -2054,10 +2054,11 @@ void main() { final GoRouter router = await createRouter(routes, tester, initialLocation: '/home'); - router.goRelative(Uri( + final String loc = Uri( path: 'page1', queryParameters: {'param1': param1}, - ).toString()); + ).toString(); + router.go('./$loc'); await tester.pumpAndSettle(); expect(find.byType(DummyScreen), findsOneWidget); From cca14548d881fa029dd073ff6f1a6c7047287b79 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 19 Jun 2024 20:01:24 +0700 Subject: [PATCH 06/26] Commit missing files during merge --- .../lib/src/information_provider.dart | 27 ------------------- packages/go_router/lib/src/path_utils.dart | 15 +++++++++++ 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/packages/go_router/lib/src/information_provider.dart b/packages/go_router/lib/src/information_provider.dart index 6588d07e35d..a019761922f 100644 --- a/packages/go_router/lib/src/information_provider.dart +++ b/packages/go_router/lib/src/information_provider.dart @@ -178,33 +178,6 @@ class GoRouteInformationProvider extends RouteInformationProvider ); } - /// Relatively go to [relativeLocation]. - void goRelative(String relativeLocation, {Object? extra}) { - assert( - !relativeLocation.startsWith('/'), - "Relative locations must not start with a '/'.", - ); - - final Uri currentUri = value.uri; - Uri newUri = Uri.parse( - currentUri.path.endsWith('/') - ? '${currentUri.path}$relativeLocation' - : '${currentUri.path}/$relativeLocation', - ); - newUri = newUri.replace(queryParameters: { - ...currentUri.queryParameters, - ...newUri.queryParameters, - }); - - _setValue( - newUri.toString(), - RouteInformationState( - extra: extra, - type: NavigatingType.go, - ), - ); - } - /// Restores the current route matches with the `matchList`. void restore(String location, {required RouteMatchList matchList}) { _setValue( diff --git a/packages/go_router/lib/src/path_utils.dart b/packages/go_router/lib/src/path_utils.dart index 49a7b33b3eb..d2c3fab1e87 100644 --- a/packages/go_router/lib/src/path_utils.dart +++ b/packages/go_router/lib/src/path_utils.dart @@ -119,6 +119,21 @@ String concatenatePaths(String parentPath, String childPath) { return '${parentPath == '/' ? '' : parentPath}/$childPath'; } +/// Concatenates two Uri. It will [concatenatePaths] the parent's and the child's paths , then merges their query parameters. +/// +/// e.g: pathA = /a?fid=f1, pathB = c/d?pid=p2, concatenatePaths(pathA, pathB) = /a/c/d?fid=1&pid=2. +Uri concatenateUris(Uri parentUri, Uri childUri) { + final Uri newUri = parentUri.replace( + path: concatenatePaths(parentUri.path, childUri.path), + queryParameters: { + ...parentUri.queryParameters, + ...childUri.queryParameters, + }, + ); + + return newUri; +} + /// Normalizes the location string. String canonicalUri(String loc) { if (loc.isEmpty) { From 975128b6fa1170dc3839c78346e1d985f0bd9c19 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 19 Jun 2024 20:05:26 +0700 Subject: [PATCH 07/26] update changelog & version --- packages/go_router/CHANGELOG.md | 4 ++++ packages/go_router/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index c8eaab75a70..1e03cbf98dd 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 14.2.1 +- Allows going to a path relatively by prefixing `./` +- Adds `TypedRelativeGoRoute` + ## 14.2.0 - Added proper `redirect` handling for `ShellRoute.$route` and `StatefulShellRoute.$route` for proper redirection handling in case of code generation. diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index eec6806cf6d..fc4f3508345 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: 14.2.0 +version: 14.2.1 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 From 6d90488b1de7922301138730366a9ba513497a7e Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 19 Jun 2024 20:19:23 +0700 Subject: [PATCH 08/26] Prevent concatenateUris from adding trailing redundant '?'. Add test for `concatenateUris` --- packages/go_router/lib/src/path_utils.dart | 15 +++++++++++---- packages/go_router/test/path_utils_test.dart | 12 ++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/go_router/lib/src/path_utils.dart b/packages/go_router/lib/src/path_utils.dart index d2c3fab1e87..268b48bee1e 100644 --- a/packages/go_router/lib/src/path_utils.dart +++ b/packages/go_router/lib/src/path_utils.dart @@ -123,12 +123,19 @@ String concatenatePaths(String parentPath, String childPath) { /// /// e.g: pathA = /a?fid=f1, pathB = c/d?pid=p2, concatenatePaths(pathA, pathB) = /a/c/d?fid=1&pid=2. Uri concatenateUris(Uri parentUri, Uri childUri) { + // Merge query parameters from both Uris. We don't return an empty map to prevent trailing '?'. + final Map? newParameters = + parentUri.queryParameters.isNotEmpty && + childUri.queryParameters.isNotEmpty + ? { + ...parentUri.queryParameters, + ...childUri.queryParameters, + } + : null; + final Uri newUri = parentUri.replace( path: concatenatePaths(parentUri.path, childUri.path), - queryParameters: { - ...parentUri.queryParameters, - ...childUri.queryParameters, - }, + queryParameters: newParameters, ); return newUri; diff --git a/packages/go_router/test/path_utils_test.dart b/packages/go_router/test/path_utils_test.dart index 5a656df135e..881a0b6ae04 100644 --- a/packages/go_router/test/path_utils_test.dart +++ b/packages/go_router/test/path_utils_test.dart @@ -93,6 +93,18 @@ void main() { verifyThrows('', ''); }); + test('concatenateUris', () { + void verify(String pathA, String pathB, String expected) { + final String result = + concatenateUris(Uri.parse(pathA), Uri.parse(pathB)).toString(); + expect(result, expected); + } + + verify('/a', 'b/c', '/a/b/c'); + verify('/', 'b', '/b'); + verify('/a?fid=f1', 'b/c?pid=p2', '/a/b/c?fid=f1&pid=p2'); + }); + test('canonicalUri', () { void verify(String path, String expected) => expect(canonicalUri(path), expected); From ccb38f92f15478dc9f26ed60a1d82385f0350169 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 19 Jun 2024 20:27:35 +0700 Subject: [PATCH 09/26] Add more `concatenateUris` test. Fix joining params --- packages/go_router/lib/src/path_utils.dart | 2 +- packages/go_router/test/path_utils_test.dart | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/go_router/lib/src/path_utils.dart b/packages/go_router/lib/src/path_utils.dart index 268b48bee1e..19de05d8da0 100644 --- a/packages/go_router/lib/src/path_utils.dart +++ b/packages/go_router/lib/src/path_utils.dart @@ -125,7 +125,7 @@ String concatenatePaths(String parentPath, String childPath) { Uri concatenateUris(Uri parentUri, Uri childUri) { // Merge query parameters from both Uris. We don't return an empty map to prevent trailing '?'. final Map? newParameters = - parentUri.queryParameters.isNotEmpty && + parentUri.queryParameters.isNotEmpty || childUri.queryParameters.isNotEmpty ? { ...parentUri.queryParameters, diff --git a/packages/go_router/test/path_utils_test.dart b/packages/go_router/test/path_utils_test.dart index 881a0b6ae04..78e11dd67f3 100644 --- a/packages/go_router/test/path_utils_test.dart +++ b/packages/go_router/test/path_utils_test.dart @@ -102,6 +102,10 @@ void main() { verify('/a', 'b/c', '/a/b/c'); verify('/', 'b', '/b'); + + // Test with parameters + verify('/a?fid=f1', 'b/c', '/a/b/c?fid=f1'); + verify('/a', 'b/c?pid=p2', '/a/b/c?pid=p2'); verify('/a?fid=f1', 'b/c?pid=p2', '/a/b/c?fid=f1&pid=p2'); }); From 80d85d65202493159fd2735e0a58f14a35a706b8 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 10 Jul 2024 11:13:08 +0700 Subject: [PATCH 10/26] update example description --- packages/go_router/example/lib/go_relative.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/go_router/example/lib/go_relative.dart b/packages/go_router/example/lib/go_relative.dart index 54f17293d2f..f59faa9e76c 100644 --- a/packages/go_router/example/lib/go_relative.dart +++ b/packages/go_router/example/lib/go_relative.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -/// This sample app demonstrates how to use GoRoute.goRelative. +/// This sample app demonstrates how to use go relatively with GoRouter.go('./$path'). void main() => runApp(const MyApp()); /// The route configuration. From a09aa94a82a01ae7d2b3beedaaead6f9e4e065e3 Mon Sep 17 00:00:00 2001 From: Thang Date: Fri, 19 Jul 2024 18:31:53 +0700 Subject: [PATCH 11/26] Make concatenateUris not merging parameters, only take them from childUri --- packages/go_router/lib/src/path_utils.dart | 20 ++++++-------------- packages/go_router/test/go_router_test.dart | 2 +- packages/go_router/test/path_utils_test.dart | 4 ++-- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/go_router/lib/src/path_utils.dart b/packages/go_router/lib/src/path_utils.dart index 19de05d8da0..247f17db14c 100644 --- a/packages/go_router/lib/src/path_utils.dart +++ b/packages/go_router/lib/src/path_utils.dart @@ -119,25 +119,17 @@ String concatenatePaths(String parentPath, String childPath) { return '${parentPath == '/' ? '' : parentPath}/$childPath'; } -/// Concatenates two Uri. It will [concatenatePaths] the parent's and the child's paths , then merges their query parameters. +/// Concatenates two Uri. It will [concatenatePaths] the parent's and the child's paths, and take only the child's parameters. /// -/// e.g: pathA = /a?fid=f1, pathB = c/d?pid=p2, concatenatePaths(pathA, pathB) = /a/c/d?fid=1&pid=2. +/// e.g: pathA = /a?fid=f1, pathB = c/d?pid=p2, concatenatePaths(pathA, pathB) = /a/c/d?pid=2. Uri concatenateUris(Uri parentUri, Uri childUri) { - // Merge query parameters from both Uris. We don't return an empty map to prevent trailing '?'. - final Map? newParameters = - parentUri.queryParameters.isNotEmpty || - childUri.queryParameters.isNotEmpty - ? { - ...parentUri.queryParameters, - ...childUri.queryParameters, - } - : null; - - final Uri newUri = parentUri.replace( + Uri newUri = parentUri.replace( path: concatenatePaths(parentUri.path, childUri.path), - queryParameters: newParameters, + queryParameters: childUri.queryParameters, ); + // Parse the new normalized uri to remove unnecessary parts, like the trailing '?'. + newUri = Uri.parse(canonicalUri(newUri.toString())); return newUri; } diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index d8a6316faec..eea3a8fdef6 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -1898,7 +1898,7 @@ void main() { path: 'person', builder: (BuildContext context, GoRouterState state) { expect(state.uri.queryParameters, - {'fid': fid, 'pid': pid}); + {'pid': pid}); return const PersonScreen('dummy', 'dummy'); }, ), diff --git a/packages/go_router/test/path_utils_test.dart b/packages/go_router/test/path_utils_test.dart index 78e11dd67f3..d25a56f246e 100644 --- a/packages/go_router/test/path_utils_test.dart +++ b/packages/go_router/test/path_utils_test.dart @@ -104,9 +104,9 @@ void main() { verify('/', 'b', '/b'); // Test with parameters - verify('/a?fid=f1', 'b/c', '/a/b/c?fid=f1'); + verify('/a?fid=f1', 'b/c', '/a/b/c'); verify('/a', 'b/c?pid=p2', '/a/b/c?pid=p2'); - verify('/a?fid=f1', 'b/c?pid=p2', '/a/b/c?fid=f1&pid=p2'); + verify('/a?fid=f1', 'b/c?pid=p2', '/a/b/c?pid=p2'); }); test('canonicalUri', () { From a174cbe73b6f5c8de2ab08f53a30aa1a8c56878b Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 10 Jul 2024 11:26:36 +0700 Subject: [PATCH 12/26] Add GoRelativeRouteConfig --- packages/go_router_builder/CHANGELOG.md | 4 + .../lib/src/go_router_generator.dart | 1 + .../lib/src/route_config.dart | 236 +++++++++++++++++- packages/go_router_builder/pubspec.yaml | 2 +- 4 files changed, 240 insertions(+), 3 deletions(-) diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index 3332a70e1b8..8357de4d3f0 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.7.1 + +- Adds `TypedRelativeGoRoute` annotation which supports relative routes. + ## 2.7.0 - Adds an example and a test with `onExit`. diff --git a/packages/go_router_builder/lib/src/go_router_generator.dart b/packages/go_router_builder/lib/src/go_router_generator.dart index e094d1f98ed..1032b78873d 100644 --- a/packages/go_router_builder/lib/src/go_router_generator.dart +++ b/packages/go_router_builder/lib/src/go_router_generator.dart @@ -15,6 +15,7 @@ const String _routeDataUrl = 'package:go_router/src/route_data.dart'; const Map _annotations = { 'TypedGoRoute': 'GoRouteData', + 'TypedRelativeRoute': 'GoRouteData', 'TypedShellRoute': 'ShellRouteData', 'TypedStatefulShellBranch': 'StatefulShellBranchData', 'TypedStatefulShellRoute': 'StatefulShellRouteData', diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index 0cfa7a3928c..f10e6ff2655 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -209,8 +209,10 @@ class GoRouteConfig extends RouteBaseConfig { RouteBaseConfig? config = this; while (config != null) { - if (config is GoRouteConfig) { - pathSegments.add(config.path); + if (config + case GoRouteConfig(:final String path) || + GoRelativeRouteConfig(:final String path)) { + pathSegments.add(path); } config = config.parent; } @@ -424,6 +426,219 @@ extension $_extensionName on $_className { String get dataConvertionFunctionName => r'$route'; } +/// The configuration to generate class declarations for a GoRouteData. +class GoRelativeRouteConfig extends RouteBaseConfig { + GoRelativeRouteConfig._({ + required this.path, + required this.parentNavigatorKey, + required super.routeDataClass, + required super.parent, + }) : super._(); + + /// The path of the GoRoute to be created by this configuration. + final String path; + + /// The parent navigator key. + final String? parentNavigatorKey; + + late final Set _pathParams = pathParametersFromPattern(path); + + // construct path bits using parent bits + // if there are any queryParam objects, add in the `queryParam` bits + String get _locationArgs { + final Map pathParameters = Map.fromEntries( + _pathParams.map((String pathParameter) { + // 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(pathParameter)?.returnType; + final String value = + '\${Uri.encodeComponent(${_encodeFor(pathParameter)}${type?.isEnum ?? false ? '!' : ''})}'; + return MapEntry(pathParameter, value); + }), + ); + final String location = patternToPath(path, pathParameters); + return "'$location'"; + } + + ParameterElement? get _extraParam => _ctor.parameters + .singleWhereOrNull((ParameterElement element) => element.isExtraField); + + String get _fromStateConstructor { + final StringBuffer buffer = StringBuffer('=>'); + if (_ctor.isConst && + _ctorParams.isEmpty && + _ctorQueryParams.isEmpty && + _extraParam == null) { + buffer.writeln('const '); + } + + buffer.writeln('$_className('); + for (final ParameterElement param in [ + ..._ctorParams, + ..._ctorQueryParams, + if (_extraParam != null) _extraParam!, + ]) { + buffer.write(_decodeFor(param)); + } + buffer.writeln(');'); + + return buffer.toString(); + } + + String _decodeFor(ParameterElement element) { + if (element.isRequired) { + if (element.type.nullabilitySuffix == NullabilitySuffix.question && + _pathParams.contains(element.name)) { + throw InvalidGenerationSourceError( + 'Required parameters in the path cannot be nullable.', + element: element, + ); + } + } + final String fromStateExpression = decodeParameter(element, _pathParams); + + if (element.isPositional) { + return '$fromStateExpression,'; + } + + if (element.isNamed) { + return '${element.name}: $fromStateExpression,'; + } + + throw InvalidGenerationSourceError( + '$likelyIssueMessage (param not named or positional)', + element: element, + ); + } + + String _encodeFor(String fieldName) { + final PropertyAccessorElement? field = _field(fieldName); + if (field == null) { + throw InvalidGenerationSourceError( + 'Could not find a field for the path parameter "$fieldName".', + element: routeDataClass, + ); + } + + return encodeField(field); + } + + String get _locationQueryParams { + if (_ctorQueryParams.isEmpty) { + return ''; + } + + final StringBuffer buffer = StringBuffer('queryParams: {\n'); + + for (final ParameterElement param in _ctorQueryParams) { + final String parameterName = param.name; + + final List conditions = []; + if (param.hasDefaultValue) { + if (param.type.isNullableType) { + throw NullableDefaultValueError(param); + } + conditions.add('$parameterName != ${param.defaultValueCode!}'); + } else if (param.type.isNullableType) { + conditions.add('$parameterName != null'); + } + String line = ''; + if (conditions.isNotEmpty) { + line = 'if (${conditions.join(' && ')}) '; + } + line += '${escapeDartString(parameterName.kebab)}: ' + '${_encodeFor(parameterName)},'; + + buffer.writeln(line); + } + + buffer.writeln('},'); + + return buffer.toString(); + } + + late final List _ctorParams = + _ctor.parameters.where((ParameterElement element) { + if (_pathParams.contains(element.name)) { + return true; + } + return false; + }).toList(); + + late final List _ctorQueryParams = _ctor.parameters + .where((ParameterElement element) => + !_pathParams.contains(element.name) && !element.isExtraField) + .toList(); + + ConstructorElement get _ctor { + final ConstructorElement? ctor = routeDataClass.unnamedConstructor; + + if (ctor == null) { + throw InvalidGenerationSourceError( + 'Missing default constructor', + element: routeDataClass, + ); + } + return ctor; + } + + @override + Iterable classDeclarations() => [ + _extensionDefinition, + ..._enumDeclarations(), + ]; + + String get _extensionDefinition => ''' +extension $_extensionName on $_className { + static $_className _fromState(GoRouterState state) $_fromStateConstructor + + String get location => './\${GoRouteData.\$location($_locationArgs,$_locationQueryParams)}'; + + void go(BuildContext context) => + context.go(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); +} +'''; + + /// Returns code representing the constant maps that contain the `enum` to + /// [String] mapping for each referenced enum. + Iterable _enumDeclarations() { + final Set enumParamTypes = {}; + + for (final ParameterElement ctorParam in [ + ..._ctorParams, + ..._ctorQueryParams, + ]) { + DartType potentialEnumType = ctorParam.type; + if (potentialEnumType is ParameterizedType && + (ctorParam.type as ParameterizedType).typeArguments.isNotEmpty) { + potentialEnumType = + (ctorParam.type as ParameterizedType).typeArguments.first; + } + + if (potentialEnumType.isEnum) { + enumParamTypes.add(potentialEnumType as InterfaceType); + } + } + return enumParamTypes.map(_enumMapConst); + } + + @override + String get factorConstructorParameters => + 'factory: $_extensionName._fromState,'; + + @override + String get routeConstructorParameters => ''' + path: ${escapeDartString(path)}, + ${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'} +'''; + + @override + String get routeDataClassName => 'GoRouteData'; + + @override + String get dataConvertionFunctionName => r'$route'; +} + /// Represents a `TypedGoRoute` annotation to the builder. abstract class RouteBaseConfig { RouteBaseConfig._({ @@ -550,6 +765,23 @@ abstract class RouteBaseConfig { parameterName: r'$parentNavigatorKey', ), ); + case 'TypedRelativeGoRoute': + final ConstantReader pathValue = reader.read('path'); + if (pathValue.isNull) { + throw InvalidGenerationSourceError( + 'Missing `path` value on annotation.', + element: element, + ); + } + value = GoRelativeRouteConfig._( + path: pathValue.stringValue, + routeDataClass: classElement, + parent: parent, + parentNavigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$parentNavigatorKey', + ), + ); default: throw UnsupportedError('Unrecognized type $typeName'); } diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 0e6e10b6b3d..1edee2d1586 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: 2.7.0 +version: 2.8.0 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 From 4cb033487e7d02b5d046bceb55b364faa64c1833 Mon Sep 17 00:00:00 2001 From: Thang Date: Fri, 19 Jul 2024 19:54:04 +0700 Subject: [PATCH 13/26] Add test, examples and example tests for go_router_builder. Temporarily use dependency_overrides to take local go_router --- .../example/lib/go_relative.dart | 156 ++++++++++++++++++ .../example/lib/go_relative.g.dart | 71 ++++++++ .../go_router_builder/example/pubspec.yaml | 4 + .../example/test/go_relative_test.dart | 29 ++++ packages/go_router_builder/pubspec.yaml | 4 + .../test_inputs/go_relative.dart | 37 +++++ .../test_inputs/go_relative.dart.expect | 88 ++++++++++ 7 files changed, 389 insertions(+) create mode 100644 packages/go_router_builder/example/lib/go_relative.dart create mode 100644 packages/go_router_builder/example/lib/go_relative.g.dart create mode 100644 packages/go_router_builder/example/test/go_relative_test.dart create mode 100644 packages/go_router_builder/test_inputs/go_relative.dart create mode 100644 packages/go_router_builder/test_inputs/go_relative.dart.expect diff --git a/packages/go_router_builder/example/lib/go_relative.dart b/packages/go_router_builder/example/lib/go_relative.dart new file mode 100644 index 00000000000..640523161bf --- /dev/null +++ b/packages/go_router_builder/example/lib/go_relative.dart @@ -0,0 +1,156 @@ +// 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. + +// ignore_for_file: public_member_api_docs, unreachable_from_main + +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +part 'go_relative.g.dart'; + +void main() => runApp(const MyApp()); + +/// The main app. +class MyApp extends StatelessWidget { + /// Constructs a [MyApp] + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + routerConfig: _router, + ); + } +} + +/// The route configuration. +final GoRouter _router = GoRouter( + routes: $appRoutes, +); +const TypedRelativeGoRoute detailRoute = + TypedRelativeGoRoute( + path: 'details/:detailId', + routes: >[ + TypedRelativeGoRoute(path: 'settings/:settingId'), + ], +); + +@TypedGoRoute( + path: '/', + routes: >[detailRoute], +) +class HomeRoute extends GoRouteData { + @override + Widget build(BuildContext context, GoRouterState state) { + return const HomeScreen(); + } +} + +class DetailsRoute extends GoRouteData { + const DetailsRoute({required this.detailId}); + final String detailId; + + @override + Widget build(BuildContext context, GoRouterState state) { + return DetailsScreen(id: detailId); + } +} + +class SettingsRoute extends GoRouteData { + const SettingsRoute({ + required this.settingId, + }); + final String settingId; + + @override + Widget build(BuildContext context, GoRouterState state) { + return SettingsScreen(id: settingId); + } +} + +/// The home screen +class HomeScreen extends StatefulWidget { + /// Constructs a [HomeScreen] + const HomeScreen({super.key}); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Home Screen')), + body: Center( + child: ElevatedButton( + onPressed: () { + const DetailsRoute(detailId: 'DetailsId').go(context); + }, + child: const Text('Go to the Details screen'), + ), + ), + ); + } +} + +/// The details screen +class DetailsScreen extends StatelessWidget { + /// Constructs a [DetailsScreen] + const DetailsScreen({ + super.key, + required this.id, + }); + + final String id; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Details Screen $id')), + body: Center( + child: Column( + children: [ + ElevatedButton( + onPressed: () => HomeRoute().go(context), + child: const Text('Go back'), + ), + ElevatedButton( + onPressed: () => const SettingsRoute( + settingId: 'SettingsId', + ).go(context), + child: const Text('Go to the Settings screen'), + ), + ], + ), + ), + ); + } +} + +/// The details screen +class SettingsScreen extends StatelessWidget { + /// Constructs a [SettingsScreen] + const SettingsScreen({ + super.key, + required this.id, + }); + + final String id; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Settings Screen $id')), + body: Center( + child: TextButton( + onPressed: () { + context.pop(); + }, + child: const Text('Go back'), + ), + ), + ); + } +} diff --git a/packages/go_router_builder/example/lib/go_relative.g.dart b/packages/go_router_builder/example/lib/go_relative.g.dart new file mode 100644 index 00000000000..2df63906645 --- /dev/null +++ b/packages/go_router_builder/example/lib/go_relative.g.dart @@ -0,0 +1,71 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: always_specify_types, public_member_api_docs + +part of 'go_relative.dart'; + +// ************************************************************************** +// GoRouterGenerator +// ************************************************************************** + +List get $appRoutes => [ + $homeRoute, + ]; + +RouteBase get $homeRoute => GoRouteData.$route( + path: '/', + factory: $HomeRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'details/:detailId', + factory: $DetailsRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'settings/:settingId', + factory: $SettingsRouteExtension._fromState, + ), + ], + ), + ], + ); + +extension $HomeRouteExtension on HomeRoute { + static HomeRoute _fromState(GoRouterState state) => HomeRoute(); + + String get location => GoRouteData.$location( + '/', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} + +extension $DetailsRouteExtension on DetailsRoute { + static DetailsRoute _fromState(GoRouterState state) => DetailsRoute( + detailId: state.pathParameters['detailId']!, + ); + + String get location => './${GoRouteData.$location( + 'details/${Uri.encodeComponent(detailId)}', + )}'; + + void go(BuildContext context) => context.go(location); +} + +extension $SettingsRouteExtension on SettingsRoute { + static SettingsRoute _fromState(GoRouterState state) => SettingsRoute( + settingId: state.pathParameters['settingId']!, + ); + + String get location => './${GoRouteData.$location( + 'settings/${Uri.encodeComponent(settingId)}', + )}'; + + void go(BuildContext context) => context.go(location); +} diff --git a/packages/go_router_builder/example/pubspec.yaml b/packages/go_router_builder/example/pubspec.yaml index bc02b13402e..18e225d0681 100644 --- a/packages/go_router_builder/example/pubspec.yaml +++ b/packages/go_router_builder/example/pubspec.yaml @@ -21,5 +21,9 @@ dev_dependencies: path: .. test: ^1.17.0 +dependency_overrides: + go_router: + path: ../../go_router + flutter: uses-material-design: true diff --git a/packages/go_router_builder/example/test/go_relative_test.dart b/packages/go_router_builder/example/test/go_relative_test.dart new file mode 100644 index 00000000000..23292e8ffd7 --- /dev/null +++ b/packages/go_router_builder/example/test/go_relative_test.dart @@ -0,0 +1,29 @@ +// 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_test/flutter_test.dart'; +import 'package:go_router_builder_example/go_relative.dart' as example; + +void main() { + testWidgets('example works', (WidgetTester tester) async { + await tester.pumpWidget(const example.MyApp()); + expect(find.byType(example.HomeScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Details screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.DetailsScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Settings screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.SettingsScreen), findsOneWidget); + + await tester.tap(find.text('Go back')); + await tester.pumpAndSettle(); + expect(find.byType(example.DetailsScreen), findsOneWidget); + + await tester.tap(find.text('Go back')); + await tester.pumpAndSettle(); + expect(find.byType(example.HomeScreen), findsOneWidget); + }); +} diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 1edee2d1586..76d904c065a 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -29,6 +29,10 @@ dev_dependencies: go_router: ^14.0.0 test: ^1.20.0 +dependency_overrides: + go_router: + path: ../go_router + topics: - codegen - deep-linking diff --git a/packages/go_router_builder/test_inputs/go_relative.dart b/packages/go_router_builder/test_inputs/go_relative.dart new file mode 100644 index 00000000000..f45c0f2569c --- /dev/null +++ b/packages/go_router_builder/test_inputs/go_relative.dart @@ -0,0 +1,37 @@ +// 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:go_router/go_router.dart'; + +const TypedRelativeGoRoute relativeRoute = + TypedRelativeGoRoute( + path: 'relative-route', + routes: >[ + TypedRelativeGoRoute(path: 'inner-relative-route') + ], +); + +@TypedGoRoute( + path: 'route-1', + routes: >[relativeRoute], +) +class Route1 extends GoRouteData { + const Route1(); +} + +@TypedGoRoute( + path: 'route-2', + routes: >[relativeRoute], +) +class Route2 extends GoRouteData { + const Route2(); +} + +class RelativeRoute extends GoRouteData { + const RelativeRoute(); +} + +class InnerRelativeRoute extends GoRouteData { + const InnerRelativeRoute(); +} diff --git a/packages/go_router_builder/test_inputs/go_relative.dart.expect b/packages/go_router_builder/test_inputs/go_relative.dart.expect new file mode 100644 index 00000000000..d491d6562ad --- /dev/null +++ b/packages/go_router_builder/test_inputs/go_relative.dart.expect @@ -0,0 +1,88 @@ +RouteBase get $route1 => GoRouteData.$route( + path: 'route-1', + factory: $Route1Extension._fromState, + routes: [ + GoRouteData.$route( + path: 'relative-route', + factory: $RelativeRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'inner-relative-route', + factory: $InnerRelativeRouteExtension._fromState, + ), + ], + ), + ], + ); + +extension $Route1Extension on Route1 { + static Route1 _fromState(GoRouterState state) => const Route1(); + + String get location => GoRouteData.$location( + 'route-1', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} + +extension $RelativeRouteExtension on RelativeRoute { + static RelativeRoute _fromState(GoRouterState state) => const RelativeRoute(); + + String get location => './${GoRouteData.$location( + 'relative-route', + )}'; + + void go(BuildContext context) => context.go(location); +} + +extension $InnerRelativeRouteExtension on InnerRelativeRoute { + static InnerRelativeRoute _fromState(GoRouterState state) => + const InnerRelativeRoute(); + + String get location => './${GoRouteData.$location( + 'inner-relative-route', + )}'; + + void go(BuildContext context) => context.go(location); +} + +RouteBase get $route2 => GoRouteData.$route( + path: 'route-2', + factory: $Route2Extension._fromState, + routes: [ + GoRouteData.$route( + path: 'relative-route', + factory: $RelativeRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'inner-relative-route', + factory: $InnerRelativeRouteExtension._fromState, + ), + ], + ), + ], + ); + +extension $Route2Extension on Route2 { + static Route2 _fromState(GoRouterState state) => const Route2(); + + String get location => GoRouteData.$location( + 'route-2', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} From ceaa318a0f1fa12493e0c214e3da68cb3e11a277 Mon Sep 17 00:00:00 2001 From: Thang Date: Fri, 19 Jul 2024 21:38:53 +0700 Subject: [PATCH 14/26] Add relativeLocation, push, pushReplacement & replace to the RelativeRoute's extension --- .../go_router_builder/lib/src/route_config.dart | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index f10e6ff2655..1236dc26534 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -592,10 +592,20 @@ class GoRelativeRouteConfig extends RouteBaseConfig { extension $_extensionName on $_className { static $_className _fromState(GoRouterState state) $_fromStateConstructor - String get location => './\${GoRouteData.\$location($_locationArgs,$_locationQueryParams)}'; + String get location => GoRouteData.\$location($_locationArgs,$_locationQueryParams); + String get relativeLocation => './\$location'; void go(BuildContext context) => - context.go(location${_extraParam != null ? ', extra: $extraFieldName' : ''}); + context.go(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); + + Future push(BuildContext context) => + context.push(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); + + void pushReplacement(BuildContext context) => + context.pushReplacement(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); + + void replace(BuildContext context) => + context.replace(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); } '''; From 07b4a238dabf633f55fbd9d8dd7fe24c587573f8 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 22 Jan 2025 15:06:59 +0700 Subject: [PATCH 15/26] update go_router package dependency --- packages/go_router_builder/pubspec.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 8c6d24360ab..4463cce2aa0 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -26,16 +26,12 @@ dev_dependencies: dart_style: '>=2.3.7 <4.0.0' flutter: sdk: flutter - go_router: ^14.0.0 + go_router: ^14.6.3 leak_tracker_flutter_testing: ">=3.0.0" package_config: ^2.1.1 pub_semver: ^2.1.5 test: ^1.20.0 -dependency_overrides: - go_router: - path: ../go_router - topics: - codegen - deep-linking From 6008b8bb6a59a2d0e76fc11f80769f828391e6c8 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 22 Jan 2025 15:17:33 +0700 Subject: [PATCH 16/26] Fix merge issues --- packages/go_router/CHANGELOG.md | 1 + packages/go_router/lib/src/path_utils.dart | 14 -------------- packages/go_router/pubspec.yaml | 2 +- packages/go_router/test/path_utils_test.dart | 16 ---------------- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 4c631d7caa6..fc8d5b8d548 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,4 +1,5 @@ ## 14.6.5 + - Adds `TypedRelativeGoRoute` ## 14.6.4 diff --git a/packages/go_router/lib/src/path_utils.dart b/packages/go_router/lib/src/path_utils.dart index 035fe774ce1..8bcb62a3c38 100644 --- a/packages/go_router/lib/src/path_utils.dart +++ b/packages/go_router/lib/src/path_utils.dart @@ -126,20 +126,6 @@ Uri concatenateUris(Uri parentUri, Uri childUri) { return newUri; } -/// Concatenates two Uri. It will [concatenatePaths] the parent's and the child's paths, and take only the child's parameters. -/// -/// e.g: pathA = /a?fid=f1, pathB = c/d?pid=p2, concatenatePaths(pathA, pathB) = /a/c/d?pid=2. -Uri concatenateUris(Uri parentUri, Uri childUri) { - Uri newUri = parentUri.replace( - path: concatenatePaths(parentUri.path, childUri.path), - queryParameters: childUri.queryParameters, - ); - - // Parse the new normalized uri to remove unnecessary parts, like the trailing '?'. - newUri = Uri.parse(canonicalUri(newUri.toString())); - return newUri; -} - /// Normalizes the location string. String canonicalUri(String loc) { if (loc.isEmpty) { diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 20b44d03844..7600be29884 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: 14.6.6 +version: 14.6.5 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/path_utils_test.dart b/packages/go_router/test/path_utils_test.dart index 8a0eb1a9238..b13599c74a5 100644 --- a/packages/go_router/test/path_utils_test.dart +++ b/packages/go_router/test/path_utils_test.dart @@ -109,22 +109,6 @@ void main() { verify('/a?fid=f1#f', 'b/c?pid=p2#', '/a/b/c?pid=p2#'); }); - test('concatenateUris', () { - void verify(String pathA, String pathB, String expected) { - final String result = - concatenateUris(Uri.parse(pathA), Uri.parse(pathB)).toString(); - expect(result, expected); - } - - verify('/a', 'b/c', '/a/b/c'); - verify('/', 'b', '/b'); - - // Test with parameters - verify('/a?fid=f1', 'b/c', '/a/b/c'); - verify('/a', 'b/c?pid=p2', '/a/b/c?pid=p2'); - verify('/a?fid=f1', 'b/c?pid=p2', '/a/b/c?pid=p2'); - }); - test('canonicalUri', () { void verify(String path, String expected) => expect(canonicalUri(path), expected); From d2fbc0ebe52aaf11cea198f094b92dc7423603ee Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 22 Jan 2025 15:32:45 +0700 Subject: [PATCH 17/26] temporarily add dependency_override --- packages/go_router_builder/pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 4463cce2aa0..19889010b8b 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -32,6 +32,10 @@ dev_dependencies: pub_semver: ^2.1.5 test: ^1.20.0 +dependency_overrides: + go_router: + path: ../go_router + topics: - codegen - deep-linking From 8b5fb4d4990fb050cd5f20b94fffe23c07834cf5 Mon Sep 17 00:00:00 2001 From: Thang Date: Tue, 4 Feb 2025 02:04:48 +0700 Subject: [PATCH 18/26] change relative route actions to have suffix `Relative` --- .../lib/src/route_config.dart | 8 +++--- .../test_inputs/go_relative.dart.expect | 28 +++++++++++++++---- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index 1236dc26534..f341f0940ec 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -595,16 +595,16 @@ extension $_extensionName on $_className { String get location => GoRouteData.\$location($_locationArgs,$_locationQueryParams); String get relativeLocation => './\$location'; - void go(BuildContext context) => + void goRelative(BuildContext context) => context.go(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - Future push(BuildContext context) => + Future pushRelative(BuildContext context) => context.push(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - void pushReplacement(BuildContext context) => + void pushReplacementRelative(BuildContext context) => context.pushReplacement(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - void replace(BuildContext context) => + void replaceRelative(BuildContext context) => context.replace(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); } '''; diff --git a/packages/go_router_builder/test_inputs/go_relative.dart.expect b/packages/go_router_builder/test_inputs/go_relative.dart.expect index d491d6562ad..5e1275f5e24 100644 --- a/packages/go_router_builder/test_inputs/go_relative.dart.expect +++ b/packages/go_router_builder/test_inputs/go_relative.dart.expect @@ -35,22 +35,38 @@ extension $Route1Extension on Route1 { extension $RelativeRouteExtension on RelativeRoute { static RelativeRoute _fromState(GoRouterState state) => const RelativeRoute(); - String get location => './${GoRouteData.$location( + String get location => GoRouteData.$location( 'relative-route', - )}'; + ); + String get relativeLocation => './$location'; - void go(BuildContext context) => context.go(location); + void goRelative(BuildContext context) => context.go(relativeLocation); + + Future pushRelative(BuildContext context) => context.push(relativeLocation); + + void pushReplacementRelative(BuildContext context) => + context.pushReplacement(relativeLocation); + + void replaceRelative(BuildContext context) => context.replace(relativeLocation); } extension $InnerRelativeRouteExtension on InnerRelativeRoute { static InnerRelativeRoute _fromState(GoRouterState state) => const InnerRelativeRoute(); - String get location => './${GoRouteData.$location( + String get location => GoRouteData.$location( 'inner-relative-route', - )}'; + ); + String get relativeLocation => './$location'; - void go(BuildContext context) => context.go(location); + void goRelative(BuildContext context) => context.go(relativeLocation); + + Future pushRelative(BuildContext context) => context.push(relativeLocation); + + void pushReplacementRelative(BuildContext context) => + context.pushReplacement(relativeLocation); + + void replaceRelative(BuildContext context) => context.replace(relativeLocation); } RouteBase get $route2 => GoRouteData.$route( From 02c3d7b63d5fb5eb8423514984a2185cf013352a Mon Sep 17 00:00:00 2001 From: Thang Date: Tue, 4 Feb 2025 22:16:15 +0700 Subject: [PATCH 19/26] Fix example --- .../example/lib/go_relative.dart | 4 +-- .../example/lib/go_relative.g.dart | 34 ++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/packages/go_router_builder/example/lib/go_relative.dart b/packages/go_router_builder/example/lib/go_relative.dart index 640523161bf..31ccc8e6c3c 100644 --- a/packages/go_router_builder/example/lib/go_relative.dart +++ b/packages/go_router_builder/example/lib/go_relative.dart @@ -86,7 +86,7 @@ class _HomeScreenState extends State { body: Center( child: ElevatedButton( onPressed: () { - const DetailsRoute(detailId: 'DetailsId').go(context); + const DetailsRoute(detailId: 'DetailsId').goRelative(context); }, child: const Text('Go to the Details screen'), ), @@ -119,7 +119,7 @@ class DetailsScreen extends StatelessWidget { ElevatedButton( onPressed: () => const SettingsRoute( settingId: 'SettingsId', - ).go(context), + ).goRelative(context), child: const Text('Go to the Settings screen'), ), ], diff --git a/packages/go_router_builder/example/lib/go_relative.g.dart b/packages/go_router_builder/example/lib/go_relative.g.dart index 2df63906645..e76190dcca7 100644 --- a/packages/go_router_builder/example/lib/go_relative.g.dart +++ b/packages/go_router_builder/example/lib/go_relative.g.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: always_specify_types, public_member_api_docs - part of 'go_relative.dart'; // ************************************************************************** @@ -51,11 +49,21 @@ extension $DetailsRouteExtension on DetailsRoute { detailId: state.pathParameters['detailId']!, ); - String get location => './${GoRouteData.$location( + String get location => GoRouteData.$location( 'details/${Uri.encodeComponent(detailId)}', - )}'; + ); + String get relativeLocation => './$location'; - void go(BuildContext context) => context.go(location); + void goRelative(BuildContext context) => context.go(relativeLocation); + + Future pushRelative(BuildContext context) => + context.push(relativeLocation); + + void pushReplacementRelative(BuildContext context) => + context.pushReplacement(relativeLocation); + + void replaceRelative(BuildContext context) => + context.replace(relativeLocation); } extension $SettingsRouteExtension on SettingsRoute { @@ -63,9 +71,19 @@ extension $SettingsRouteExtension on SettingsRoute { settingId: state.pathParameters['settingId']!, ); - String get location => './${GoRouteData.$location( + String get location => GoRouteData.$location( 'settings/${Uri.encodeComponent(settingId)}', - )}'; + ); + String get relativeLocation => './$location'; - void go(BuildContext context) => context.go(location); + void goRelative(BuildContext context) => context.go(relativeLocation); + + Future pushRelative(BuildContext context) => + context.push(relativeLocation); + + void pushReplacementRelative(BuildContext context) => + context.pushReplacement(relativeLocation); + + void replaceRelative(BuildContext context) => + context.replace(relativeLocation); } From 72c06de008c84b1a371e2fa44cd1c88ce2a5ec67 Mon Sep 17 00:00:00 2001 From: Thang Date: Thu, 6 Feb 2025 20:33:19 +0700 Subject: [PATCH 20/26] Update go_relative test --- .../example/lib/go_relative.dart | 74 +++++++++++++++---- .../example/lib/go_relative.g.dart | 33 +++++++++ .../example/test/go_relative_test.dart | 26 +++++++ 3 files changed, 117 insertions(+), 16 deletions(-) diff --git a/packages/go_router_builder/example/lib/go_relative.dart b/packages/go_router_builder/example/lib/go_relative.dart index 31ccc8e6c3c..26f49772d50 100644 --- a/packages/go_router_builder/example/lib/go_relative.dart +++ b/packages/go_router_builder/example/lib/go_relative.dart @@ -38,7 +38,13 @@ const TypedRelativeGoRoute detailRoute = @TypedGoRoute( path: '/', - routes: >[detailRoute], + routes: >[ + TypedGoRoute( + path: '/dashboard', + routes: >[detailRoute], + ), + detailRoute, + ], ) class HomeRoute extends GoRouteData { @override @@ -47,6 +53,13 @@ class HomeRoute extends GoRouteData { } } +class DashboardRoute extends GoRouteData { + @override + Widget build(BuildContext context, GoRouterState state) { + return const DashboardScreen(); + } +} + class DetailsRoute extends GoRouteData { const DetailsRoute({required this.detailId}); final String detailId; @@ -70,26 +83,57 @@ class SettingsRoute extends GoRouteData { } /// The home screen -class HomeScreen extends StatefulWidget { +class HomeScreen extends StatelessWidget { /// Constructs a [HomeScreen] const HomeScreen({super.key}); @override - State createState() => _HomeScreenState(); + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Home Screen')), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () { + const DetailsRoute(detailId: 'DetailsId').goRelative(context); + }, + child: const Text('Go to the Details screen'), + ), + ElevatedButton( + onPressed: () { + DashboardRoute().go(context); + }, + child: const Text('Go to the Dashboard screen'), + ), + ], + ), + ); + } } -class _HomeScreenState extends State { +/// The home screen +class DashboardScreen extends StatelessWidget { + /// Constructs a [DashboardScreen] + const DashboardScreen({super.key}); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Home Screen')), - body: Center( - child: ElevatedButton( - onPressed: () { - const DetailsRoute(detailId: 'DetailsId').goRelative(context); - }, - child: const Text('Go to the Details screen'), - ), + appBar: AppBar(title: const Text('Dashboard Screen')), + body: Column( + children: [ + ElevatedButton( + onPressed: () { + const DetailsRoute(detailId: 'DetailsId').goRelative(context); + }, + child: const Text('Go to the Details screen'), + ), + ElevatedButton( + onPressed: () => context.pop(), + child: const Text('Go back'), + ), + ], ), ); } @@ -113,7 +157,7 @@ class DetailsScreen extends StatelessWidget { child: Column( children: [ ElevatedButton( - onPressed: () => HomeRoute().go(context), + onPressed: () => context.pop(), child: const Text('Go back'), ), ElevatedButton( @@ -145,9 +189,7 @@ class SettingsScreen extends StatelessWidget { appBar: AppBar(title: Text('Settings Screen $id')), body: Center( child: TextButton( - onPressed: () { - context.pop(); - }, + onPressed: () => context.pop(), child: const Text('Go back'), ), ), diff --git a/packages/go_router_builder/example/lib/go_relative.g.dart b/packages/go_router_builder/example/lib/go_relative.g.dart index e76190dcca7..1a3907739fa 100644 --- a/packages/go_router_builder/example/lib/go_relative.g.dart +++ b/packages/go_router_builder/example/lib/go_relative.g.dart @@ -14,6 +14,22 @@ RouteBase get $homeRoute => GoRouteData.$route( path: '/', factory: $HomeRouteExtension._fromState, routes: [ + GoRouteData.$route( + path: '/dashboard', + factory: $DashboardRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'details/:detailId', + factory: $DetailsRouteExtension._fromState, + routes: [ + GoRouteData.$route( + path: 'settings/:settingId', + factory: $SettingsRouteExtension._fromState, + ), + ], + ), + ], + ), GoRouteData.$route( path: 'details/:detailId', factory: $DetailsRouteExtension._fromState, @@ -44,6 +60,23 @@ extension $HomeRouteExtension on HomeRoute { void replace(BuildContext context) => context.replace(location); } +extension $DashboardRouteExtension on DashboardRoute { + static DashboardRoute _fromState(GoRouterState state) => DashboardRoute(); + + String get location => GoRouteData.$location( + '/dashboard', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} + extension $DetailsRouteExtension on DetailsRoute { static DetailsRoute _fromState(GoRouterState state) => DetailsRoute( detailId: state.pathParameters['detailId']!, diff --git a/packages/go_router_builder/example/test/go_relative_test.dart b/packages/go_router_builder/example/test/go_relative_test.dart index 23292e8ffd7..3efd323e8c2 100644 --- a/packages/go_router_builder/example/test/go_relative_test.dart +++ b/packages/go_router_builder/example/test/go_relative_test.dart @@ -10,6 +10,7 @@ void main() { await tester.pumpWidget(const example.MyApp()); expect(find.byType(example.HomeScreen), findsOneWidget); + // From Home screen, go to Details screen await tester.tap(find.text('Go to the Details screen')); await tester.pumpAndSettle(); expect(find.byType(example.DetailsScreen), findsOneWidget); @@ -25,5 +26,30 @@ void main() { await tester.tap(find.text('Go back')); await tester.pumpAndSettle(); expect(find.byType(example.HomeScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Dashboard screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.DashboardScreen), findsOneWidget); + + // From Dashboard screen, go to Details screen + await tester.tap(find.text('Go to the Details screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.DetailsScreen), findsOneWidget); + + await tester.tap(find.text('Go to the Settings screen')); + await tester.pumpAndSettle(); + expect(find.byType(example.SettingsScreen), findsOneWidget); + + await tester.tap(find.text('Go back')); + await tester.pumpAndSettle(); + expect(find.byType(example.DetailsScreen), findsOneWidget); + + await tester.tap(find.text('Go back')); + await tester.pumpAndSettle(); + expect(find.byType(example.DashboardScreen), findsOneWidget); + + await tester.tap(find.text('Go back')); + await tester.pumpAndSettle(); + expect(find.byType(example.HomeScreen), findsOneWidget); }); } From 547430394c09f9ef42544f5cbc92ac8e1bb739b7 Mon Sep 17 00:00:00 2001 From: Thang Date: Sat, 17 May 2025 23:45:18 +0700 Subject: [PATCH 21/26] fix generated file --- packages/go_router_builder/example/lib/go_relative.g.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/go_router_builder/example/lib/go_relative.g.dart b/packages/go_router_builder/example/lib/go_relative.g.dart index 1a3907739fa..abd89aee2b7 100644 --- a/packages/go_router_builder/example/lib/go_relative.g.dart +++ b/packages/go_router_builder/example/lib/go_relative.g.dart @@ -1,5 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: always_specify_types, public_member_api_docs + part of 'go_relative.dart'; // ************************************************************************** From dbf7f9d479cfc11f79c6cdb32acccb04b97a06d9 Mon Sep 17 00:00:00 2001 From: Thang Date: Sat, 17 May 2025 23:56:11 +0700 Subject: [PATCH 22/26] Fix failed test due to generated files --- .../test_inputs/go_relative.dart.expect | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/go_router_builder/test_inputs/go_relative.dart.expect b/packages/go_router_builder/test_inputs/go_relative.dart.expect index 5e1275f5e24..83ec21918dd 100644 --- a/packages/go_router_builder/test_inputs/go_relative.dart.expect +++ b/packages/go_router_builder/test_inputs/go_relative.dart.expect @@ -42,12 +42,14 @@ extension $RelativeRouteExtension on RelativeRoute { void goRelative(BuildContext context) => context.go(relativeLocation); - Future pushRelative(BuildContext context) => context.push(relativeLocation); + Future pushRelative(BuildContext context) => + context.push(relativeLocation); void pushReplacementRelative(BuildContext context) => context.pushReplacement(relativeLocation); - void replaceRelative(BuildContext context) => context.replace(relativeLocation); + void replaceRelative(BuildContext context) => + context.replace(relativeLocation); } extension $InnerRelativeRouteExtension on InnerRelativeRoute { @@ -61,12 +63,14 @@ extension $InnerRelativeRouteExtension on InnerRelativeRoute { void goRelative(BuildContext context) => context.go(relativeLocation); - Future pushRelative(BuildContext context) => context.push(relativeLocation); + Future pushRelative(BuildContext context) => + context.push(relativeLocation); void pushReplacementRelative(BuildContext context) => context.pushReplacement(relativeLocation); - void replaceRelative(BuildContext context) => context.replace(relativeLocation); + void replaceRelative(BuildContext context) => + context.replace(relativeLocation); } RouteBase get $route2 => GoRouteData.$route( From f899939687aa5d2110ab7474fc0293bc8e7cc8b4 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 9 Jul 2025 13:56:30 +0700 Subject: [PATCH 23/26] Remove GoRouteData routing methods. Update TypedRelativeGoRoute generator to use mixin instead of extension. Update tests to use appropriate mixins --- packages/go_router/lib/src/route_data.dart | 24 ------- packages/go_router/test/route_data_test.dart | 70 ------------------- .../example/lib/go_relative.dart | 8 +-- .../example/lib/go_relative.g.dart | 30 ++++---- .../lib/src/route_config.dart | 57 ++++++++++----- .../test_inputs/go_relative.dart | 13 ++-- .../test_inputs/go_relative.dart.expect | 35 +++++++--- .../test_inputs/no_mixin_relative.dart | 8 +++ .../test_inputs/no_mixin_relative.dart.expect | 1 + 9 files changed, 103 insertions(+), 143 deletions(-) create mode 100644 packages/go_router_builder/test_inputs/no_mixin_relative.dart create mode 100644 packages/go_router_builder/test_inputs/no_mixin_relative.dart.expect diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart index 236583cef5d..0bc2716be3f 100644 --- a/packages/go_router/lib/src/route_data.dart +++ b/packages/go_router/lib/src/route_data.dart @@ -133,30 +133,6 @@ abstract class GoRouteData extends RouteData { static final Expando _stateObjectExpando = Expando( 'GoRouteState to GoRouteData expando', ); - - /// The location of this route. - String get location => throw _shouldBeGeneratedError; - - /// Navigate to the route. - void go(BuildContext context) => throw _shouldBeGeneratedError; - - /// Push the route onto the page stack. - Future push(BuildContext context) => throw _shouldBeGeneratedError; - - /// Replaces the top-most page of the page stack with the route. - void pushReplacement(BuildContext context) => throw _shouldBeGeneratedError; - - /// Replaces the top-most page of the page stack with the route but treats - /// it as the same page. - /// - /// The page key will be reused. This will preserve the state and not run any - /// page animation. - /// - void replace(BuildContext context) => throw _shouldBeGeneratedError; - - static UnimplementedError get _shouldBeGeneratedError => UnimplementedError( - 'Should be generated using [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html).', - ); } /// A class to represent a [ShellRoute] in diff --git a/packages/go_router/test/route_data_test.dart b/packages/go_router/test/route_data_test.dart index 218caef690d..bb721c9ad0a 100644 --- a/packages/go_router/test/route_data_test.dart +++ b/packages/go_router/test/route_data_test.dart @@ -280,76 +280,6 @@ void main() { expect(routeWithDefaultCaseSensitivity.caseSensitive, false); }, ); - - testWidgets( - 'It should throw beacuase there is no code generated', - (WidgetTester tester) async { - final List errors = []; - - FlutterError.onError = - (FlutterErrorDetails details) => errors.add(details); - - const String errorText = 'Should be generated'; - - Widget buildWidget(void Function(BuildContext) onTap) { - return MaterialApp( - home: Builder( - builder: (BuildContext context) => GestureDetector( - child: const Text('Tap'), - onTap: () => onTap(context), - ), - ), - ); - } - - final Widget pushThrower = buildWidget((BuildContext context) { - const _GoRouteDataBuild().push(context); - }); - await tester.pumpWidget(pushThrower); - await tester.tap(find.text('Tap')); - - expect(errors.first.exception, isA()); - expect(errors.first.exception.toString(), contains(errorText)); - - errors.clear(); - - final Widget goThrower = buildWidget((BuildContext context) { - const _GoRouteDataBuild().go(context); - }); - await tester.pumpWidget(goThrower); - await tester.tap(find.text('Tap')); - - expect(errors.first.exception, isA()); - expect(errors.first.exception.toString(), contains(errorText)); - - errors.clear(); - - final Widget pushReplacementThrower = - buildWidget((BuildContext context) { - const _GoRouteDataBuild().pushReplacement(context); - }); - await tester.pumpWidget(pushReplacementThrower); - await tester.tap(find.text('Tap')); - - expect(errors.first.exception, isA()); - expect(errors.first.exception.toString(), contains(errorText)); - - errors.clear(); - - final Widget replaceThrower = buildWidget((BuildContext context) { - const _GoRouteDataBuild().pushReplacement(context); - }); - await tester.pumpWidget(replaceThrower); - await tester.tap(find.text('Tap')); - - expect(errors.first.exception, isA()); - expect(errors.first.exception.toString(), contains(errorText)); - - errors.clear(); - - FlutterError.onError = FlutterError.dumpErrorToConsole; - }, - ); }); group('ShellRouteData', () { diff --git a/packages/go_router_builder/example/lib/go_relative.dart b/packages/go_router_builder/example/lib/go_relative.dart index 26f49772d50..a431245fafe 100644 --- a/packages/go_router_builder/example/lib/go_relative.dart +++ b/packages/go_router_builder/example/lib/go_relative.dart @@ -46,21 +46,21 @@ const TypedRelativeGoRoute detailRoute = detailRoute, ], ) -class HomeRoute extends GoRouteData { +class HomeRoute extends GoRouteData with _$HomeRoute { @override Widget build(BuildContext context, GoRouterState state) { return const HomeScreen(); } } -class DashboardRoute extends GoRouteData { +class DashboardRoute extends GoRouteData with _$DashboardRoute { @override Widget build(BuildContext context, GoRouterState state) { return const DashboardScreen(); } } -class DetailsRoute extends GoRouteData { +class DetailsRoute extends GoRouteData with _$DetailsRoute { const DetailsRoute({required this.detailId}); final String detailId; @@ -70,7 +70,7 @@ class DetailsRoute extends GoRouteData { } } -class SettingsRoute extends GoRouteData { +class SettingsRoute extends GoRouteData with _$SettingsRoute { const SettingsRoute({ required this.settingId, }); diff --git a/packages/go_router_builder/example/lib/go_relative.g.dart b/packages/go_router_builder/example/lib/go_relative.g.dart index abd89aee2b7..c88a2fe7ffb 100644 --- a/packages/go_router_builder/example/lib/go_relative.g.dart +++ b/packages/go_router_builder/example/lib/go_relative.g.dart @@ -14,19 +14,19 @@ List get $appRoutes => [ RouteBase get $homeRoute => GoRouteData.$route( path: '/', - factory: $HomeRouteExtension._fromState, + factory: _$HomeRoute._fromState, routes: [ GoRouteData.$route( path: '/dashboard', - factory: $DashboardRouteExtension._fromState, + factory: _$DashboardRoute._fromState, routes: [ GoRouteData.$route( path: 'details/:detailId', - factory: $DetailsRouteExtension._fromState, + factory: _$DetailsRoute._fromState, routes: [ GoRouteData.$route( path: 'settings/:settingId', - factory: $SettingsRouteExtension._fromState, + factory: _$SettingsRoute._fromState, ), ], ), @@ -34,18 +34,18 @@ RouteBase get $homeRoute => GoRouteData.$route( ), GoRouteData.$route( path: 'details/:detailId', - factory: $DetailsRouteExtension._fromState, + factory: _$DetailsRoute._fromState, routes: [ GoRouteData.$route( path: 'settings/:settingId', - factory: $SettingsRouteExtension._fromState, + factory: _$SettingsRoute._fromState, ), ], ), ], ); -extension $HomeRouteExtension on HomeRoute { +mixin _$HomeRoute on GoRouteData { static HomeRoute _fromState(GoRouterState state) => HomeRoute(); String get location => GoRouteData.$location( @@ -62,7 +62,7 @@ extension $HomeRouteExtension on HomeRoute { void replace(BuildContext context) => context.replace(location); } -extension $DashboardRouteExtension on DashboardRoute { +mixin _$DashboardRoute on GoRouteData { static DashboardRoute _fromState(GoRouterState state) => DashboardRoute(); String get location => GoRouteData.$location( @@ -79,14 +79,17 @@ extension $DashboardRouteExtension on DashboardRoute { void replace(BuildContext context) => context.replace(location); } -extension $DetailsRouteExtension on DetailsRoute { +mixin _$DetailsRoute on GoRouteData { static DetailsRoute _fromState(GoRouterState state) => DetailsRoute( detailId: state.pathParameters['detailId']!, ); + DetailsRoute get _self => this as DetailsRoute; + String get location => GoRouteData.$location( - 'details/${Uri.encodeComponent(detailId)}', + 'details/${Uri.encodeComponent(_self.detailId)}', ); + String get relativeLocation => './$location'; void goRelative(BuildContext context) => context.go(relativeLocation); @@ -101,14 +104,17 @@ extension $DetailsRouteExtension on DetailsRoute { context.replace(relativeLocation); } -extension $SettingsRouteExtension on SettingsRoute { +mixin _$SettingsRoute on GoRouteData { static SettingsRoute _fromState(GoRouterState state) => SettingsRoute( settingId: state.pathParameters['settingId']!, ); + SettingsRoute get _self => this as SettingsRoute; + String get location => GoRouteData.$location( - 'settings/${Uri.encodeComponent(settingId)}', + 'settings/${Uri.encodeComponent(_self.settingId)}', ); + String get relativeLocation => './$location'; void goRelative(BuildContext context) => context.go(relativeLocation); diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index ffb653ea096..c097efd3265 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -418,22 +418,17 @@ class GoRouteConfig extends RouteBaseConfig { mixin $_mixinName on GoRouteData { static $_className _fromState(GoRouterState state) $_fromStateConstructor $_castedSelf - @override String get location => GoRouteData.\$location($_locationArgs,$_locationQueryParams); - @override void go(BuildContext context) => context.go(location${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); - @override Future push(BuildContext context) => context.push(location${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); - @override void replace(BuildContext context) => context.replace(location${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); } @@ -578,6 +573,16 @@ class GoRelativeRouteConfig extends RouteBaseConfig { return encodeField(field); } + String get _castedSelf { + if (_pathParams.isEmpty && + _ctorQueryParams.isEmpty && + _extraParam == null) { + return ''; + } + + return '\n$_className get $selfFieldName => this as $_className;\n'; + } + String get _locationQueryParams { if (_ctorQueryParams.isEmpty) { return ''; @@ -639,30 +644,45 @@ class GoRelativeRouteConfig extends RouteBaseConfig { @override Iterable classDeclarations() => [ - _extensionDefinition, + _mixinDefinition, ..._enumDeclarations(), ]; - String get _extensionDefinition => ''' -extension $_extensionName on $_className { - static $_className _fromState(GoRouterState state) $_fromStateConstructor + String get _mixinDefinition { + final bool hasMixin = getNodeDeclaration(routeDataClass) + ?.withClause + ?.mixinTypes + .any((NamedType e) => e.name2.toString() == _mixinName) ?? + false; + if (!hasMixin) { + throw InvalidGenerationSourceError( + 'Missing mixin clause `with $_mixinName`', + element: routeDataClass, + ); + } + return ''' +mixin $_mixinName on GoRouteData { + static $_className _fromState(GoRouterState state) $_fromStateConstructor + $_castedSelf String get location => GoRouteData.\$location($_locationArgs,$_locationQueryParams); - String get relativeLocation => './\$location'; + String get relativeLocation => './\$location'; + void goRelative(BuildContext context) => - context.go(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - + context.go(relativeLocation${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); + Future pushRelative(BuildContext context) => - context.push(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - + context.push(relativeLocation${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); + void pushReplacementRelative(BuildContext context) => - context.pushReplacement(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); - + context.pushReplacement(relativeLocation${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); + void replaceRelative(BuildContext context) => - context.replace(relativeLocation${_extraParam != null ? ', extra: $extraFieldName' : ''}); + context.replace(relativeLocation${_extraParam != null ? ', extra: $selfFieldName.$extraFieldName' : ''}); } '''; + } /// Returns code representing the constant maps that contain the `enum` to /// [String] mapping for each referenced enum. @@ -688,8 +708,7 @@ extension $_extensionName on $_className { } @override - String get factorConstructorParameters => - 'factory: $_extensionName._fromState,'; + String get factorConstructorParameters => 'factory: $_mixinName._fromState,'; @override String get routeConstructorParameters => ''' diff --git a/packages/go_router_builder/test_inputs/go_relative.dart b/packages/go_router_builder/test_inputs/go_relative.dart index f45c0f2569c..aaa53fee17e 100644 --- a/packages/go_router_builder/test_inputs/go_relative.dart +++ b/packages/go_router_builder/test_inputs/go_relative.dart @@ -4,6 +4,11 @@ import 'package:go_router/go_router.dart'; +mixin _$Route1 {} +mixin _$Route2 {} +mixin _$RelativeRoute {} +mixin _$InnerRelativeRoute {} + const TypedRelativeGoRoute relativeRoute = TypedRelativeGoRoute( path: 'relative-route', @@ -16,7 +21,7 @@ const TypedRelativeGoRoute relativeRoute = path: 'route-1', routes: >[relativeRoute], ) -class Route1 extends GoRouteData { +class Route1 extends GoRouteData with _$Route1 { const Route1(); } @@ -24,14 +29,14 @@ class Route1 extends GoRouteData { path: 'route-2', routes: >[relativeRoute], ) -class Route2 extends GoRouteData { +class Route2 extends GoRouteData with _$Route2 { const Route2(); } -class RelativeRoute extends GoRouteData { +class RelativeRoute extends GoRouteData with _$RelativeRoute { const RelativeRoute(); } -class InnerRelativeRoute extends GoRouteData { +class InnerRelativeRoute extends GoRouteData with _$InnerRelativeRoute { const InnerRelativeRoute(); } diff --git a/packages/go_router_builder/test_inputs/go_relative.dart.expect b/packages/go_router_builder/test_inputs/go_relative.dart.expect index 83ec21918dd..3c8a86950bd 100644 --- a/packages/go_router_builder/test_inputs/go_relative.dart.expect +++ b/packages/go_router_builder/test_inputs/go_relative.dart.expect @@ -1,21 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'go_relative.dart'; + +// ************************************************************************** +// GoRouterGenerator +// ************************************************************************** + +List get $appRoutes => [ + $route1, + $route2, + ]; + RouteBase get $route1 => GoRouteData.$route( path: 'route-1', - factory: $Route1Extension._fromState, + factory: _$Route1._fromState, routes: [ GoRouteData.$route( path: 'relative-route', - factory: $RelativeRouteExtension._fromState, + factory: _$RelativeRoute._fromState, routes: [ GoRouteData.$route( path: 'inner-relative-route', - factory: $InnerRelativeRouteExtension._fromState, + factory: _$InnerRelativeRoute._fromState, ), ], ), ], ); -extension $Route1Extension on Route1 { +mixin _$Route1 on GoRouteData { static Route1 _fromState(GoRouterState state) => const Route1(); String get location => GoRouteData.$location( @@ -32,12 +45,13 @@ extension $Route1Extension on Route1 { void replace(BuildContext context) => context.replace(location); } -extension $RelativeRouteExtension on RelativeRoute { +mixin _$RelativeRoute on GoRouteData { static RelativeRoute _fromState(GoRouterState state) => const RelativeRoute(); String get location => GoRouteData.$location( 'relative-route', ); + String get relativeLocation => './$location'; void goRelative(BuildContext context) => context.go(relativeLocation); @@ -52,13 +66,14 @@ extension $RelativeRouteExtension on RelativeRoute { context.replace(relativeLocation); } -extension $InnerRelativeRouteExtension on InnerRelativeRoute { +mixin _$InnerRelativeRoute on GoRouteData { static InnerRelativeRoute _fromState(GoRouterState state) => const InnerRelativeRoute(); String get location => GoRouteData.$location( 'inner-relative-route', ); + String get relativeLocation => './$location'; void goRelative(BuildContext context) => context.go(relativeLocation); @@ -75,22 +90,22 @@ extension $InnerRelativeRouteExtension on InnerRelativeRoute { RouteBase get $route2 => GoRouteData.$route( path: 'route-2', - factory: $Route2Extension._fromState, + factory: _$Route2._fromState, routes: [ GoRouteData.$route( path: 'relative-route', - factory: $RelativeRouteExtension._fromState, + factory: _$RelativeRoute._fromState, routes: [ GoRouteData.$route( path: 'inner-relative-route', - factory: $InnerRelativeRouteExtension._fromState, + factory: _$InnerRelativeRoute._fromState, ), ], ), ], ); -extension $Route2Extension on Route2 { +mixin _$Route2 on GoRouteData { static Route2 _fromState(GoRouterState state) => const Route2(); String get location => GoRouteData.$location( diff --git a/packages/go_router_builder/test_inputs/no_mixin_relative.dart b/packages/go_router_builder/test_inputs/no_mixin_relative.dart new file mode 100644 index 00000000000..871d45830c3 --- /dev/null +++ b/packages/go_router_builder/test_inputs/no_mixin_relative.dart @@ -0,0 +1,8 @@ +// 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:go_router/go_router.dart'; + +@TypedRelativeGoRoute(path: '/') +class HomeRoute extends GoRouteData {} diff --git a/packages/go_router_builder/test_inputs/no_mixin_relative.dart.expect b/packages/go_router_builder/test_inputs/no_mixin_relative.dart.expect new file mode 100644 index 00000000000..dc98f351c1f --- /dev/null +++ b/packages/go_router_builder/test_inputs/no_mixin_relative.dart.expect @@ -0,0 +1 @@ +Missing mixin clause `with _$HomeRoute` From 92f6cac8995a12b714a1d533cfff92abde2f9f25 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 9 Jul 2025 14:25:07 +0700 Subject: [PATCH 24/26] remove overrides on other tests --- .../example/lib/all_types.g.dart | 65 ------------------- .../example/lib/case_sensitive_example.g.dart | 10 --- .../example/lib/extra_example.g.dart | 15 ----- .../go_router_builder/example/lib/main.g.dart | 30 --------- .../example/lib/on_exit_example.g.dart | 10 --- .../example/lib/readme_excerpts.g.dart | 50 -------------- .../example/lib/shell_route_example.g.dart | 15 ----- .../lib/shell_route_with_keys_example.g.dart | 15 ----- .../shell_route_with_observers_example.g.dart | 15 ----- .../example/lib/simple_example.g.dart | 10 --- .../lib/stateful_shell_route_example.g.dart | 10 --- ...hell_route_initial_location_example.g.dart | 15 ----- .../test_inputs/case_sensitivity.dart.expect | 10 --- .../test_inputs/default_value.dart.expect | 5 -- .../test_inputs/enum_parameter.dart.expect | 5 -- .../test_inputs/extra_value.dart.expect | 5 -- .../iterable_with_default_value.dart.expect | 5 -- .../iterable_with_enum.dart.expect | 5 -- .../test_inputs/list.dart.expect | 5 -- .../named_escaped_route.dart.expect | 5 -- .../test_inputs/named_route.dart.expect | 5 -- .../required_extra_value.dart.expect | 5 -- ...ble_type_arguments_extra_value.dart.expect | 5 -- ...meters_not_in_path_can_be_null.dart.expect | 5 -- .../required_query_parameter.dart.expect | 5 -- .../test_inputs/set.dart.expect | 5 -- 26 files changed, 335 deletions(-) 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 6af36b14ee6..4086fc1db1b 100644 --- a/packages/go_router_builder/example/lib/all_types.g.dart +++ b/packages/go_router_builder/example/lib/all_types.g.dart @@ -75,22 +75,17 @@ mixin _$AllTypesBaseRoute on GoRouteData { static AllTypesBaseRoute _fromState(GoRouterState state) => const AllTypesBaseRoute(); - @override String get location => GoRouteData.$location( '/', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -104,7 +99,6 @@ mixin _$BigIntRoute on GoRouteData { BigIntRoute get _self => this as BigIntRoute; - @override String get location => GoRouteData.$location( '/big-int-route/${Uri.encodeComponent(_self.requiredBigIntField.toString())}', queryParams: { @@ -113,17 +107,13 @@ mixin _$BigIntRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -142,7 +132,6 @@ mixin _$BoolRoute on GoRouteData { BoolRoute get _self => this as BoolRoute; - @override String get location => GoRouteData.$location( '/bool-route/${Uri.encodeComponent(_self.requiredBoolField.toString())}', queryParams: { @@ -154,17 +143,13 @@ mixin _$BoolRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -178,7 +163,6 @@ mixin _$DateTimeRoute on GoRouteData { DateTimeRoute get _self => this as DateTimeRoute; - @override String get location => GoRouteData.$location( '/date-time-route/${Uri.encodeComponent(_self.requiredDateTimeField.toString())}', queryParams: { @@ -187,17 +171,13 @@ mixin _$DateTimeRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -216,7 +196,6 @@ mixin _$DoubleRoute on GoRouteData { DoubleRoute get _self => this as DoubleRoute; - @override String get location => GoRouteData.$location( '/double-route/${Uri.encodeComponent(_self.requiredDoubleField.toString())}', queryParams: { @@ -228,17 +207,13 @@ mixin _$DoubleRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -256,7 +231,6 @@ mixin _$IntRoute on GoRouteData { IntRoute get _self => this as IntRoute; - @override String get location => GoRouteData.$location( '/int-route/${Uri.encodeComponent(_self.requiredIntField.toString())}', queryParams: { @@ -267,17 +241,13 @@ mixin _$IntRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -295,7 +265,6 @@ mixin _$NumRoute on GoRouteData { NumRoute get _self => this as NumRoute; - @override String get location => GoRouteData.$location( '/num-route/${Uri.encodeComponent(_self.requiredNumField.toString())}', queryParams: { @@ -306,17 +275,13 @@ mixin _$NumRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -335,7 +300,6 @@ mixin _$EnumRoute on GoRouteData { EnumRoute get _self => this as EnumRoute; - @override String get location => GoRouteData.$location( '/enum-route/${Uri.encodeComponent(_$PersonDetailsEnumMap[_self.requiredEnumField]!)}', queryParams: { @@ -347,17 +311,13 @@ mixin _$EnumRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -382,7 +342,6 @@ mixin _$EnhancedEnumRoute on GoRouteData { EnhancedEnumRoute get _self => this as EnhancedEnumRoute; - @override String get location => GoRouteData.$location( '/enhanced-enum-route/${Uri.encodeComponent(_$SportDetailsEnumMap[_self.requiredEnumField]!)}', queryParams: { @@ -394,17 +353,13 @@ mixin _$EnhancedEnumRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -426,7 +381,6 @@ mixin _$StringRoute on GoRouteData { StringRoute get _self => this as StringRoute; - @override String get location => GoRouteData.$location( '/string-route/${Uri.encodeComponent(_self.requiredStringField)}', queryParams: { @@ -437,17 +391,13 @@ mixin _$StringRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -460,7 +410,6 @@ mixin _$UriRoute on GoRouteData { UriRoute get _self => this as UriRoute; - @override String get location => GoRouteData.$location( '/uri-route/${Uri.encodeComponent(_self.requiredUriField.toString())}', queryParams: { @@ -468,17 +417,13 @@ mixin _$UriRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -564,7 +509,6 @@ mixin _$IterableRoute on GoRouteData { IterableRoute get _self => this as IterableRoute; - @override String get location => GoRouteData.$location( '/iterable-route', queryParams: { @@ -629,17 +573,13 @@ mixin _$IterableRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -732,7 +672,6 @@ mixin _$IterableRouteWithDefaultValues on GoRouteData { IterableRouteWithDefaultValues get _self => this as IterableRouteWithDefaultValues; - @override String get location => GoRouteData.$location( '/iterable-route-with-default-values', queryParams: { @@ -792,17 +731,13 @@ mixin _$IterableRouteWithDefaultValues on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/case_sensitive_example.g.dart b/packages/go_router_builder/example/lib/case_sensitive_example.g.dart index 3c6a5b84e31..0144a91d8ae 100644 --- a/packages/go_router_builder/example/lib/case_sensitive_example.g.dart +++ b/packages/go_router_builder/example/lib/case_sensitive_example.g.dart @@ -22,22 +22,17 @@ mixin _$CaseSensitiveRoute on GoRouteData { static CaseSensitiveRoute _fromState(GoRouterState state) => const CaseSensitiveRoute(); - @override String get location => GoRouteData.$location( '/case-sensitive', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -51,21 +46,16 @@ mixin _$NotCaseSensitiveRoute on GoRouteData { static NotCaseSensitiveRoute _fromState(GoRouterState state) => const NotCaseSensitiveRoute(); - @override String get location => GoRouteData.$location( '/not-case-sensitive', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(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 1161326b103..9a812562eb9 100644 --- a/packages/go_router_builder/example/lib/extra_example.g.dart +++ b/packages/go_router_builder/example/lib/extra_example.g.dart @@ -27,23 +27,18 @@ mixin _$RequiredExtraRoute on GoRouteData { RequiredExtraRoute get _self => this as RequiredExtraRoute; - @override String get location => GoRouteData.$location( '/requiredExtra', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } @@ -61,23 +56,18 @@ mixin _$OptionalExtraRoute on GoRouteData { OptionalExtraRoute get _self => this as OptionalExtraRoute; - @override String get location => GoRouteData.$location( '/optionalExtra', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } @@ -90,21 +80,16 @@ RouteBase get $splashRoute => GoRouteData.$route( mixin _$SplashRoute on GoRouteData { static SplashRoute _fromState(GoRouterState state) => const SplashRoute(); - @override String get location => GoRouteData.$location( '/splash', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/main.g.dart b/packages/go_router_builder/example/lib/main.g.dart index f631d241cc0..cc8a9fc9ca8 100644 --- a/packages/go_router_builder/example/lib/main.g.dart +++ b/packages/go_router_builder/example/lib/main.g.dart @@ -43,22 +43,17 @@ RouteBase get $homeRoute => GoRouteData.$route( mixin _$HomeRoute on GoRouteData { static HomeRoute _fromState(GoRouterState state) => const HomeRoute(); - @override String get location => GoRouteData.$location( '/', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -69,22 +64,17 @@ mixin _$FamilyRoute on GoRouteData { FamilyRoute get _self => this as FamilyRoute; - @override String get location => GoRouteData.$location( '/family/${Uri.encodeComponent(_self.fid)}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -96,22 +86,17 @@ mixin _$PersonRoute on GoRouteData { PersonRoute get _self => this as PersonRoute; - @override String get location => GoRouteData.$location( '/family/${Uri.encodeComponent(_self.fid)}/person/${Uri.encodeComponent(_self.pid.toString())}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -126,23 +111,18 @@ mixin _$PersonDetailsRoute on GoRouteData { PersonDetailsRoute get _self => this as PersonDetailsRoute; - @override String get location => GoRouteData.$location( '/family/${Uri.encodeComponent(_self.fid)}/person/${Uri.encodeComponent(_self.pid.toString())}/details/${Uri.encodeComponent(_$PersonDetailsEnumMap[_self.details]!)}', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } @@ -160,22 +140,17 @@ mixin _$FamilyCountRoute on GoRouteData { FamilyCountRoute get _self => this as FamilyCountRoute; - @override String get location => GoRouteData.$location( '/family-count/${Uri.encodeComponent(_self.count.toString())}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -196,7 +171,6 @@ mixin _$LoginRoute on GoRouteData { LoginRoute get _self => this as LoginRoute; - @override String get location => GoRouteData.$location( '/login', queryParams: { @@ -204,16 +178,12 @@ mixin _$LoginRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/on_exit_example.g.dart b/packages/go_router_builder/example/lib/on_exit_example.g.dart index 458ccc0371b..96adc67f02e 100644 --- a/packages/go_router_builder/example/lib/on_exit_example.g.dart +++ b/packages/go_router_builder/example/lib/on_exit_example.g.dart @@ -26,43 +26,33 @@ RouteBase get $homeRoute => GoRouteData.$route( mixin _$HomeRoute on GoRouteData { static HomeRoute _fromState(GoRouterState state) => const HomeRoute(); - @override String get location => GoRouteData.$location( '/', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } mixin _$SubRoute on GoRouteData { static SubRoute _fromState(GoRouterState state) => const SubRoute(); - @override String get location => GoRouteData.$location( '/sub-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/readme_excerpts.g.dart b/packages/go_router_builder/example/lib/readme_excerpts.g.dart index 6a6ff0c69b6..435b665571a 100644 --- a/packages/go_router_builder/example/lib/readme_excerpts.g.dart +++ b/packages/go_router_builder/example/lib/readme_excerpts.g.dart @@ -34,22 +34,17 @@ RouteBase get $homeRoute => GoRouteData.$route( mixin _$HomeRoute on GoRouteData { static HomeRoute _fromState(GoRouterState state) => const HomeRoute(); - @override String get location => GoRouteData.$location( '/', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -60,22 +55,17 @@ mixin _$FamilyRoute on GoRouteData { FamilyRoute get _self => this as FamilyRoute; - @override String get location => GoRouteData.$location( '/family/${Uri.encodeComponent(_self.fid ?? '')}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -91,7 +81,6 @@ mixin _$LoginRoute on GoRouteData { LoginRoute get _self => this as LoginRoute; - @override String get location => GoRouteData.$location( '/login', queryParams: { @@ -99,17 +88,13 @@ mixin _$LoginRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -126,7 +111,6 @@ mixin _$MyRoute on GoRouteData { MyRoute get _self => this as MyRoute; - @override String get location => GoRouteData.$location( '/my-route', queryParams: { @@ -135,17 +119,13 @@ mixin _$MyRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -162,23 +142,18 @@ mixin _$PersonRouteWithExtra on GoRouteData { PersonRouteWithExtra get _self => this as PersonRouteWithExtra; - @override String get location => GoRouteData.$location( '/person', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } @@ -198,7 +173,6 @@ mixin _$HotdogRouteWithEverything on GoRouteData { HotdogRouteWithEverything get _self => this as HotdogRouteWithEverything; - @override String get location => GoRouteData.$location( '/${Uri.encodeComponent(_self.ketchup.toString())}', queryParams: { @@ -206,18 +180,14 @@ mixin _$HotdogRouteWithEverything on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } @@ -247,7 +217,6 @@ mixin _$BooksRoute on GoRouteData { BooksRoute get _self => this as BooksRoute; - @override String get location => GoRouteData.$location( '/books', queryParams: { @@ -256,17 +225,13 @@ mixin _$BooksRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -299,22 +264,17 @@ mixin _$MyMaterialRouteWithKey on GoRouteData { static MyMaterialRouteWithKey _fromState(GoRouterState state) => const MyMaterialRouteWithKey(); - @override String get location => GoRouteData.$location( '/my-material-route-with-key', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -326,22 +286,17 @@ RouteBase get $fancyRoute => GoRouteData.$route( mixin _$FancyRoute on GoRouteData { static FancyRoute _fromState(GoRouterState state) => const FancyRoute(); - @override String get location => GoRouteData.$location( '/fancy', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -365,21 +320,16 @@ extension $MyShellRouteDataExtension on MyShellRouteData { mixin _$MyGoRouteData on GoRouteData { static MyGoRouteData _fromState(GoRouterState state) => const MyGoRouteData(); - @override String get location => GoRouteData.$location( 'my-go-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(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 0b2e61ebee3..0c578ced16e 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 @@ -35,44 +35,34 @@ extension $MyShellRouteDataExtension on MyShellRouteData { mixin _$FooRouteData on GoRouteData { static FooRouteData _fromState(GoRouterState state) => const FooRouteData(); - @override String get location => GoRouteData.$location( '/foo', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } mixin _$BarRouteData on GoRouteData { static BarRouteData _fromState(GoRouterState state) => const BarRouteData(); - @override String get location => GoRouteData.$location( '/bar', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -84,21 +74,16 @@ RouteBase get $loginRoute => GoRouteData.$route( mixin _$LoginRoute on GoRouteData { static LoginRoute _fromState(GoRouterState state) => const LoginRoute(); - @override String get location => GoRouteData.$location( '/login', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(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 759588b2d28..b29ef63d13b 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 @@ -42,22 +42,17 @@ extension $MyShellRouteDataExtension on MyShellRouteData { mixin _$HomeRouteData on GoRouteData { static HomeRouteData _fromState(GoRouterState state) => const HomeRouteData(); - @override String get location => GoRouteData.$location( '/home', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -65,22 +60,17 @@ mixin _$UsersRouteData on GoRouteData { static UsersRouteData _fromState(GoRouterState state) => const UsersRouteData(); - @override String get location => GoRouteData.$location( '/users', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -91,21 +81,16 @@ mixin _$UserRouteData on GoRouteData { UserRouteData get _self => this as UserRouteData; - @override String get location => GoRouteData.$location( '/users/${Uri.encodeComponent(_self.id.toString())}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/shell_route_with_observers_example.g.dart b/packages/go_router_builder/example/lib/shell_route_with_observers_example.g.dart index e510a5f3a80..c5e6afd6a1c 100644 --- a/packages/go_router_builder/example/lib/shell_route_with_observers_example.g.dart +++ b/packages/go_router_builder/example/lib/shell_route_with_observers_example.g.dart @@ -41,22 +41,17 @@ extension $MyShellRouteDataExtension on MyShellRouteData { mixin _$HomeRouteData on GoRouteData { static HomeRouteData _fromState(GoRouterState state) => const HomeRouteData(); - @override String get location => GoRouteData.$location( '/home', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -64,22 +59,17 @@ mixin _$UsersRouteData on GoRouteData { static UsersRouteData _fromState(GoRouterState state) => const UsersRouteData(); - @override String get location => GoRouteData.$location( '/users', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -90,21 +80,16 @@ mixin _$UserRouteData on GoRouteData { UserRouteData get _self => this as UserRouteData; - @override String get location => GoRouteData.$location( '/users/${Uri.encodeComponent(_self.id.toString())}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(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 4ecd74e3cbf..02ccb6e1c23 100644 --- a/packages/go_router_builder/example/lib/simple_example.g.dart +++ b/packages/go_router_builder/example/lib/simple_example.g.dart @@ -27,22 +27,17 @@ RouteBase get $homeRoute => GoRouteData.$route( mixin _$HomeRoute on GoRouteData { static HomeRoute _fromState(GoRouterState state) => const HomeRoute(); - @override String get location => GoRouteData.$location( '/', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -53,21 +48,16 @@ mixin _$FamilyRoute on GoRouteData { FamilyRoute get _self => this as FamilyRoute; - @override String get location => GoRouteData.$location( '/family/${Uri.encodeComponent(_self.familyId)}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart b/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart index d0eaa8ddf6a..d0a5ea2f26e 100644 --- a/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart +++ b/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart @@ -47,22 +47,17 @@ mixin _$DetailsARouteData on GoRouteData { static DetailsARouteData _fromState(GoRouterState state) => const DetailsARouteData(); - @override String get location => GoRouteData.$location( '/detailsA', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -70,21 +65,16 @@ mixin _$DetailsBRouteData on GoRouteData { static DetailsBRouteData _fromState(GoRouterState state) => const DetailsBRouteData(); - @override String get location => GoRouteData.$location( '/detailsB', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/example/lib/stateful_shell_route_initial_location_example.g.dart b/packages/go_router_builder/example/lib/stateful_shell_route_initial_location_example.g.dart index c7e63a1fc7f..7093db69b54 100644 --- a/packages/go_router_builder/example/lib/stateful_shell_route_initial_location_example.g.dart +++ b/packages/go_router_builder/example/lib/stateful_shell_route_initial_location_example.g.dart @@ -51,22 +51,17 @@ extension $MainShellRouteDataExtension on MainShellRouteData { mixin _$HomeRouteData on GoRouteData { static HomeRouteData _fromState(GoRouterState state) => const HomeRouteData(); - @override String get location => GoRouteData.$location( '/home', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -79,22 +74,17 @@ mixin _$NotificationsRouteData on GoRouteData { NotificationsRouteData get _self => this as NotificationsRouteData; - @override String get location => GoRouteData.$location( '/notifications/${Uri.encodeComponent(_$NotificationsPageSectionEnumMap[_self.section]!)}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -108,22 +98,17 @@ mixin _$OrdersRouteData on GoRouteData { static OrdersRouteData _fromState(GoRouterState state) => const OrdersRouteData(); - @override String get location => GoRouteData.$location( '/orders', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/case_sensitivity.dart.expect b/packages/go_router_builder/test_inputs/case_sensitivity.dart.expect index acbc044d5bf..bf577320bad 100644 --- a/packages/go_router_builder/test_inputs/case_sensitivity.dart.expect +++ b/packages/go_router_builder/test_inputs/case_sensitivity.dart.expect @@ -7,22 +7,17 @@ mixin _$CaseSensitiveRoute on GoRouteData { static CaseSensitiveRoute _fromState(GoRouterState state) => CaseSensitiveRoute(); - @override String get location => GoRouteData.$location( '/case-sensitive-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } @@ -36,21 +31,16 @@ mixin _$NotCaseSensitiveRoute on GoRouteData { static NotCaseSensitiveRoute _fromState(GoRouterState state) => NotCaseSensitiveRoute(); - @override String get location => GoRouteData.$location( '/not-case-sensitive-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/default_value.dart.expect b/packages/go_router_builder/test_inputs/default_value.dart.expect index 9302c4b2346..49468768b5e 100644 --- a/packages/go_router_builder/test_inputs/default_value.dart.expect +++ b/packages/go_router_builder/test_inputs/default_value.dart.expect @@ -12,7 +12,6 @@ mixin _$DefaultValueRoute on GoRouteData { DefaultValueRoute get _self => this as DefaultValueRoute; - @override String get location => GoRouteData.$location( '/default-value-route', queryParams: { @@ -20,17 +19,13 @@ mixin _$DefaultValueRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/enum_parameter.dart.expect b/packages/go_router_builder/test_inputs/enum_parameter.dart.expect index 341e1bab282..029203dfe4d 100644 --- a/packages/go_router_builder/test_inputs/enum_parameter.dart.expect +++ b/packages/go_router_builder/test_inputs/enum_parameter.dart.expect @@ -10,22 +10,17 @@ mixin _$EnumParam on GoRouteData { EnumParam get _self => this as EnumParam; - @override String get location => GoRouteData.$location( '/${Uri.encodeComponent(_$EnumTestEnumMap[_self.y]!)}', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/extra_value.dart.expect b/packages/go_router_builder/test_inputs/extra_value.dart.expect index 944b8a4b25c..d86f0587dad 100644 --- a/packages/go_router_builder/test_inputs/extra_value.dart.expect +++ b/packages/go_router_builder/test_inputs/extra_value.dart.expect @@ -13,7 +13,6 @@ mixin _$ExtraValueRoute on GoRouteData { ExtraValueRoute get _self => this as ExtraValueRoute; - @override String get location => GoRouteData.$location( '/default-value-route', queryParams: { @@ -21,18 +20,14 @@ mixin _$ExtraValueRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } diff --git a/packages/go_router_builder/test_inputs/iterable_with_default_value.dart.expect b/packages/go_router_builder/test_inputs/iterable_with_default_value.dart.expect index 35e4cb75fb5..fc3a553e15e 100644 --- a/packages/go_router_builder/test_inputs/iterable_with_default_value.dart.expect +++ b/packages/go_router_builder/test_inputs/iterable_with_default_value.dart.expect @@ -14,7 +14,6 @@ mixin _$IterableDefaultValueRoute on GoRouteData { IterableDefaultValueRoute get _self => this as IterableDefaultValueRoute; - @override String get location => GoRouteData.$location( '/iterable-default-value-route', queryParams: { @@ -23,17 +22,13 @@ mixin _$IterableDefaultValueRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/iterable_with_enum.dart.expect b/packages/go_router_builder/test_inputs/iterable_with_enum.dart.expect index ef7fd9fec7c..b39e6a4f6a3 100644 --- a/packages/go_router_builder/test_inputs/iterable_with_enum.dart.expect +++ b/packages/go_router_builder/test_inputs/iterable_with_enum.dart.expect @@ -14,7 +14,6 @@ mixin _$IterableWithEnumRoute on GoRouteData { IterableWithEnumRoute get _self => this as IterableWithEnumRoute; - @override String get location => GoRouteData.$location( '/iterable-with-enum', queryParams: { @@ -25,17 +24,13 @@ mixin _$IterableWithEnumRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/list.dart.expect b/packages/go_router_builder/test_inputs/list.dart.expect index abe23c4c4f1..f8b4caf03c9 100644 --- a/packages/go_router_builder/test_inputs/list.dart.expect +++ b/packages/go_router_builder/test_inputs/list.dart.expect @@ -27,7 +27,6 @@ mixin _$ListRoute on GoRouteData { ListRoute get _self => this as ListRoute; - @override String get location => GoRouteData.$location( '/list-route', queryParams: { @@ -41,17 +40,13 @@ mixin _$ListRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/named_escaped_route.dart.expect b/packages/go_router_builder/test_inputs/named_escaped_route.dart.expect index df9ab5f52d5..b5574b9159c 100644 --- a/packages/go_router_builder/test_inputs/named_escaped_route.dart.expect +++ b/packages/go_router_builder/test_inputs/named_escaped_route.dart.expect @@ -8,21 +8,16 @@ mixin _$NamedEscapedRoute on GoRouteData { static NamedEscapedRoute _fromState(GoRouterState state) => NamedEscapedRoute(); - @override String get location => GoRouteData.$location( '/named-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/named_route.dart.expect b/packages/go_router_builder/test_inputs/named_route.dart.expect index b3cf1c42c42..5d6f00509f1 100644 --- a/packages/go_router_builder/test_inputs/named_route.dart.expect +++ b/packages/go_router_builder/test_inputs/named_route.dart.expect @@ -7,21 +7,16 @@ RouteBase get $namedRoute => GoRouteData.$route( mixin _$NamedRoute on GoRouteData { static NamedRoute _fromState(GoRouterState state) => NamedRoute(); - @override String get location => GoRouteData.$location( '/named-route', ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/required_extra_value.dart.expect b/packages/go_router_builder/test_inputs/required_extra_value.dart.expect index 662c55b6758..3eb6990b6c2 100644 --- a/packages/go_router_builder/test_inputs/required_extra_value.dart.expect +++ b/packages/go_router_builder/test_inputs/required_extra_value.dart.expect @@ -11,23 +11,18 @@ mixin _$RequiredExtraValueRoute on GoRouteData { RequiredExtraValueRoute get _self => this as RequiredExtraValueRoute; - @override String get location => GoRouteData.$location( '/default-value-route', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } diff --git a/packages/go_router_builder/test_inputs/required_nullable_type_arguments_extra_value.dart.expect b/packages/go_router_builder/test_inputs/required_nullable_type_arguments_extra_value.dart.expect index 2a181ac8576..dadb4da739f 100644 --- a/packages/go_router_builder/test_inputs/required_nullable_type_arguments_extra_value.dart.expect +++ b/packages/go_router_builder/test_inputs/required_nullable_type_arguments_extra_value.dart.expect @@ -14,23 +14,18 @@ mixin _$RequiredNullableTypeArgumentsExtraValueRoute on GoRouteData { RequiredNullableTypeArgumentsExtraValueRoute get _self => this as RequiredNullableTypeArgumentsExtraValueRoute; - @override String get location => GoRouteData.$location( '/default-value-route', ); - @override void go(BuildContext context) => context.go(location, extra: _self.$extra); - @override Future push(BuildContext context) => context.push(location, extra: _self.$extra); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location, extra: _self.$extra); - @override void replace(BuildContext context) => context.replace(location, extra: _self.$extra); } diff --git a/packages/go_router_builder/test_inputs/required_parameters_not_in_path_can_be_null.dart.expect b/packages/go_router_builder/test_inputs/required_parameters_not_in_path_can_be_null.dart.expect index 60c1c0f6a25..64a7518ee75 100644 --- a/packages/go_router_builder/test_inputs/required_parameters_not_in_path_can_be_null.dart.expect +++ b/packages/go_router_builder/test_inputs/required_parameters_not_in_path_can_be_null.dart.expect @@ -12,7 +12,6 @@ mixin _$NullableRequiredParamNotInPath on GoRouteData { NullableRequiredParamNotInPath get _self => this as NullableRequiredParamNotInPath; - @override String get location => GoRouteData.$location( 'bob', queryParams: { @@ -20,17 +19,13 @@ mixin _$NullableRequiredParamNotInPath on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/required_query_parameter.dart.expect b/packages/go_router_builder/test_inputs/required_query_parameter.dart.expect index 23487d96d6e..99e48d0a5c6 100644 --- a/packages/go_router_builder/test_inputs/required_query_parameter.dart.expect +++ b/packages/go_router_builder/test_inputs/required_query_parameter.dart.expect @@ -12,7 +12,6 @@ mixin _$NonNullableRequiredParamNotInPath on GoRouteData { NonNullableRequiredParamNotInPath get _self => this as NonNullableRequiredParamNotInPath; - @override String get location => GoRouteData.$location( 'bob', queryParams: { @@ -20,16 +19,12 @@ mixin _$NonNullableRequiredParamNotInPath on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } diff --git a/packages/go_router_builder/test_inputs/set.dart.expect b/packages/go_router_builder/test_inputs/set.dart.expect index 69d25393d59..632395241e9 100644 --- a/packages/go_router_builder/test_inputs/set.dart.expect +++ b/packages/go_router_builder/test_inputs/set.dart.expect @@ -27,7 +27,6 @@ mixin _$SetRoute on GoRouteData { SetRoute get _self => this as SetRoute; - @override String get location => GoRouteData.$location( '/set-route', queryParams: { @@ -41,17 +40,13 @@ mixin _$SetRoute on GoRouteData { }, ); - @override void go(BuildContext context) => context.go(location); - @override Future push(BuildContext context) => context.push(location); - @override void pushReplacement(BuildContext context) => context.pushReplacement(location); - @override void replace(BuildContext context) => context.replace(location); } From f98505e47302734a87e3328fc55dc4fbee1965f4 Mon Sep 17 00:00:00 2001 From: Thang Date: Wed, 9 Jul 2025 15:09:32 +0700 Subject: [PATCH 25/26] make sure relative go route generated code resembles typed go route as much as possible. Add case sensitive support. Fix failing tests --- packages/go_router/lib/src/route_data.dart | 12 +++++ .../lib/src/go_router_generator.dart | 2 +- .../lib/src/route_config.dart | 50 +++++++++++++------ packages/go_router_builder/pubspec.yaml | 2 +- .../test_inputs/go_relative.dart.expect | 13 ----- 5 files changed, 49 insertions(+), 30 deletions(-) diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart index 0bc2716be3f..8c6ec6adc30 100644 --- a/packages/go_router/lib/src/route_data.dart +++ b/packages/go_router/lib/src/route_data.dart @@ -413,6 +413,7 @@ class TypedRelativeGoRoute extends TypedRoute { const TypedRelativeGoRoute({ required this.path, this.routes = const >[], + this.caseSensitive = true, }); /// The relative path that corresponds to this route. @@ -426,6 +427,17 @@ class TypedRelativeGoRoute extends TypedRoute { /// /// See [RouteBase.routes]. final List> routes; + + /// Determines whether the route matching is case sensitive. + /// + /// When `true`, the path must match the specified case. For example, + /// a route with `path: '/family/:fid'` will not match `/FaMiLy/f2`. + /// + /// When `false`, the path matching is case insensitive. The route + /// with `path: '/family/:fid'` will match `/FaMiLy/f2`. + /// + /// Defaults to `true`. + final bool caseSensitive; } /// A superclass for each typed shell route descendant diff --git a/packages/go_router_builder/lib/src/go_router_generator.dart b/packages/go_router_builder/lib/src/go_router_generator.dart index d93356e873f..f28fa387918 100644 --- a/packages/go_router_builder/lib/src/go_router_generator.dart +++ b/packages/go_router_builder/lib/src/go_router_generator.dart @@ -16,7 +16,7 @@ const String _routeDataUrl = 'package:go_router/src/route_data.dart'; const Map _annotations = { 'TypedGoRoute': 'GoRouteData', - 'TypedRelativeRoute': 'GoRouteData', + 'TypedRelativeGoRoute': 'GoRouteData', 'TypedShellRoute': 'ShellRouteData', 'TypedStatefulShellBranch': 'StatefulShellBranchData', 'TypedStatefulShellRoute': 'StatefulShellRouteData', diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index c097efd3265..3f7aa762c3d 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -480,6 +480,7 @@ mixin $_mixinName on GoRouteData { class GoRelativeRouteConfig extends RouteBaseConfig { GoRelativeRouteConfig._({ required this.path, + required this.caseSensitive, required this.parentNavigatorKey, required super.routeDataClass, required super.parent, @@ -488,6 +489,9 @@ class GoRelativeRouteConfig extends RouteBaseConfig { /// The path of the GoRoute to be created by this configuration. final String path; + /// The case sensitivity of the GoRelativeRoute to be created by this configuration. + final bool caseSensitive; + /// The parent navigator key. final String? parentNavigatorKey; @@ -501,9 +505,21 @@ class GoRelativeRouteConfig extends RouteBaseConfig { // 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(pathParameter)?.returnType; - final String value = - '\${Uri.encodeComponent(${_encodeFor(pathParameter)}${type?.isEnum ?? false ? '!' : ''})}'; - return MapEntry(pathParameter, value); + + final StringBuffer valueBuffer = StringBuffer(); + + valueBuffer.write(r'${Uri.encodeComponent('); + valueBuffer.write(_encodeFor(pathParameter)); + + if (type?.isEnum ?? false) { + valueBuffer.write('!'); + } else if (type?.isNullableType ?? false) { + valueBuffer.write("?? ''"); + } + + valueBuffer.write(')}'); + + return MapEntry(pathParameter, valueBuffer.toString()); }), ); final String location = patternToPath(path, pathParameters); @@ -535,6 +551,16 @@ class GoRelativeRouteConfig extends RouteBaseConfig { return buffer.toString(); } + String get _castedSelf { + if (_pathParams.isEmpty && + _ctorQueryParams.isEmpty && + _extraParam == null) { + return ''; + } + + return '\n$_className get $selfFieldName => this as $_className;\n'; + } + String _decodeFor(ParameterElement element) { if (element.isRequired) { if (element.type.nullabilitySuffix == NullabilitySuffix.question && @@ -573,16 +599,6 @@ class GoRelativeRouteConfig extends RouteBaseConfig { return encodeField(field); } - String get _castedSelf { - if (_pathParams.isEmpty && - _ctorQueryParams.isEmpty && - _extraParam == null) { - return ''; - } - - return '\n$_className get $selfFieldName => this as $_className;\n'; - } - String get _locationQueryParams { if (_ctorQueryParams.isEmpty) { return ''; @@ -598,9 +614,11 @@ class GoRelativeRouteConfig extends RouteBaseConfig { if (param.type.isNullableType) { throw NullableDefaultValueError(param); } - conditions.add('$parameterName != ${param.defaultValueCode!}'); + conditions.add( + compareField(param, parameterName, param.defaultValueCode!), + ); } else if (param.type.isNullableType) { - conditions.add('$parameterName != null'); + conditions.add('$selfFieldName.$parameterName != null'); } String line = ''; if (conditions.isNotEmpty) { @@ -863,8 +881,10 @@ abstract class RouteBaseConfig { element: element, ); } + final ConstantReader caseSensitiveValue = reader.read('caseSensitive'); value = GoRelativeRouteConfig._( path: pathValue.stringValue, + caseSensitive: caseSensitiveValue.boolValue, routeDataClass: classElement, parent: parent, parentNavigatorKey: _generateParameterGetterCode( diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 6c274b01382..ce26cb65cc1 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: 3.0.1 +version: 3.0.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_inputs/go_relative.dart.expect b/packages/go_router_builder/test_inputs/go_relative.dart.expect index 3c8a86950bd..6d877058682 100644 --- a/packages/go_router_builder/test_inputs/go_relative.dart.expect +++ b/packages/go_router_builder/test_inputs/go_relative.dart.expect @@ -1,16 +1,3 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'go_relative.dart'; - -// ************************************************************************** -// GoRouterGenerator -// ************************************************************************** - -List get $appRoutes => [ - $route1, - $route2, - ]; - RouteBase get $route1 => GoRouteData.$route( path: 'route-1', factory: _$Route1._fromState, From 20fd5d629a3e98c3c5e490df011ee547895a9ebc Mon Sep 17 00:00:00 2001 From: Thang Date: Thu, 10 Jul 2025 12:32:53 +0700 Subject: [PATCH 26/26] update changelog --- packages/go_router/CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 175e66afe19..cffa4b727e8 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 16.0.1 + +- Adds `TypedRelativeGoRoute` + ## 16.0.0 - **BREAKING CHANGE** @@ -13,10 +17,6 @@ - Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. - Fixes typo in API docs. -## 15.1.3 - -- Adds `TypedRelativeGoRoute` - ## 15.1.2 - Fixes focus request propagation from `GoRouter` to `Navigator` by properly handling the `requestFocus` parameter.