diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 969415b10d55..65807f91f5be 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,6 +1,10 @@ +## 14.4.0 + +- Adds current state getter on `GoRouter` that returns the current `GoRouterState`. + ## 14.3.0 -- Added missing implementation for the routerNeglect parameter in GoRouter. +- Adds missing implementation for the routerNeglect parameter in GoRouter. ## 14.2.9 diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index b28f70149119..94496657ed78 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -13,6 +13,7 @@ import 'configuration.dart'; import 'match.dart'; import 'misc/errors.dart'; import 'route.dart'; +import 'state.dart'; /// GoRouter implementation of [RouterDelegate]. class GoRouterDelegate extends RouterDelegate @@ -169,6 +170,11 @@ class GoRouterDelegate extends RouterDelegate }()); } + /// The top [GoRouterState], the state of the route that was + /// last used in either [GoRouter.go] or [GoRouter.push]. + GoRouterState? get state => currentConfiguration.last + .buildState(_configuration, currentConfiguration); + /// For use by the Router architecture as part of the RouterDelegate. GlobalKey get navigatorKey => _configuration.navigatorKey; diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart index f8afff38cb14..11f40f505cac 100644 --- a/packages/go_router/lib/src/router.dart +++ b/packages/go_router/lib/src/router.dart @@ -255,6 +255,14 @@ class GoRouter implements RouterConfig { }()); } + /// The top [GoRouterState], the state of the route that was + /// last used in either [GoRouter.go] or [GoRouter.push]. + /// + /// Accessing this property via GoRouter.of(context).state will not + /// cause rebuild if the state has changed, consider using + /// GoRouterState.of(context) instead. + GoRouterState? get state => routerDelegate.state; + /// Whether the imperative API affects browser URL bar. /// /// The Imperative APIs refer to [push], [pushReplacement], or [replace]. diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 4e086f245594..7195e85f1f66 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.3.0 +version: 14.4.0 repository: https://github.com/flutter/packages/tree/main/packages/go_router issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22 diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart index e2c2d1b5cfc1..a852805265c7 100644 --- a/packages/go_router/test/go_router_test.dart +++ b/packages/go_router/test/go_router_test.dart @@ -5474,6 +5474,78 @@ void main() { ); }); + testWidgets( + 'should return the current GoRouterState when router.currentState is called', + (WidgetTester tester) async { + final List routes = [ + GoRoute( + name: 'home', + path: '/', + builder: (BuildContext context, GoRouterState state) => + const HomeScreen()), + GoRoute( + name: 'books', + path: '/books', + builder: (BuildContext context, GoRouterState state) => + const Text('books')), + GoRoute( + name: 'boats', + path: '/boats', + builder: (BuildContext context, GoRouterState state) => + const Text('boats')), + ShellRoute( + builder: (BuildContext context, GoRouterState state, Widget child) => + child, + routes: [ + GoRoute( + name: 'tulips', + path: '/tulips', + builder: (BuildContext context, GoRouterState state) => + const Text('tulips'), + ), + ], + ) + ]; + + final GoRouter router = await createRouter(routes, tester); + await tester.pumpAndSettle(); + + GoRouterState? state = router.state; + expect(state?.name, 'home'); + expect(state?.fullPath, '/'); + + router.go('/books'); + await tester.pumpAndSettle(); + state = router.state; + expect(state?.name, 'books'); + expect(state?.fullPath, '/books'); + + router.push('/boats'); + await tester.pumpAndSettle(); + state = router.state; + expect(state?.name, 'boats'); + expect(state?.fullPath, '/boats'); + + router.pop(); + await tester.pumpAndSettle(); + state = router.state; + expect(state?.name, 'books'); + expect(state?.fullPath, '/books'); + + router.go('/tulips'); + await tester.pumpAndSettle(); + state = router.state; + expect(state?.name, 'tulips'); + expect(state?.fullPath, '/tulips'); + + router.go('/books'); + router.push('/tulips'); + await tester.pumpAndSettle(); + state = router.state; + expect(state?.name, 'tulips'); + expect(state?.fullPath, '/tulips'); + }); + testWidgets('should allow route paths without leading /', (WidgetTester tester) async { final List routes = [