-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[go_router] Refactored RouteMatchList and imperative APIs (#5497)
This pr refactor RouteMatchList to be a tree structure. Added a common base class RouteMatchBase. It is extended by both RouteMatch and ShellRouteMatch. The RouteMatch is for GoRoute, and is always a leaf node The ShellRouteMatch is for ShellRouteBase, and is always and intermediate node with a list of child RouteMatchBase[s]. This pr also redo how push is processed. Will add a doc explain this shortly. This is a breaking change, will write a migration guide soon. fixes flutter/flutter#134524 fixes flutter/flutter#130406 fixes flutter/flutter#126365 fixes flutter/flutter#125752 fixes flutter/flutter#120791 fixes flutter/flutter#120665 fixes flutter/flutter#113001 fixes flutter/flutter#110512
- Loading branch information
Showing
23 changed files
with
1,688 additions
and
892 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
packages/go_router/example/lib/push_with_shell_route.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// 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 scenario demonstrates the behavior when pushing ShellRoute in various | ||
// scenario. | ||
// | ||
// This example have three routes, /shell1, /shell2, and /regular-route. The | ||
// /shell1 and /shell2 are nested in different ShellRoutes. The /regular-route | ||
// is a simple GoRoute. | ||
|
||
void main() { | ||
runApp(PushWithShellRouteExampleApp()); | ||
} | ||
|
||
/// An example demonstrating how to use [ShellRoute] | ||
class PushWithShellRouteExampleApp extends StatelessWidget { | ||
/// Creates a [PushWithShellRouteExampleApp] | ||
PushWithShellRouteExampleApp({super.key}); | ||
|
||
final GoRouter _router = GoRouter( | ||
initialLocation: '/home', | ||
debugLogDiagnostics: true, | ||
routes: <RouteBase>[ | ||
ShellRoute( | ||
builder: (BuildContext context, GoRouterState state, Widget child) { | ||
return ScaffoldForShell1(child: child); | ||
}, | ||
routes: <RouteBase>[ | ||
GoRoute( | ||
path: '/home', | ||
builder: (BuildContext context, GoRouterState state) { | ||
return const Home(); | ||
}, | ||
), | ||
GoRoute( | ||
path: '/shell1', | ||
pageBuilder: (_, __) => const NoTransitionPage<void>( | ||
child: Center( | ||
child: Text('shell1 body'), | ||
), | ||
), | ||
), | ||
], | ||
), | ||
ShellRoute( | ||
builder: (BuildContext context, GoRouterState state, Widget child) { | ||
return ScaffoldForShell2(child: child); | ||
}, | ||
routes: <RouteBase>[ | ||
GoRoute( | ||
path: '/shell2', | ||
builder: (BuildContext context, GoRouterState state) { | ||
return const Center(child: Text('shell2 body')); | ||
}, | ||
), | ||
], | ||
), | ||
GoRoute( | ||
path: '/regular-route', | ||
builder: (BuildContext context, GoRouterState state) { | ||
return const Scaffold( | ||
body: Center(child: Text('regular route')), | ||
); | ||
}, | ||
), | ||
], | ||
); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialApp.router( | ||
title: 'Flutter Demo', | ||
theme: ThemeData( | ||
primarySwatch: Colors.blue, | ||
), | ||
routerConfig: _router, | ||
); | ||
} | ||
} | ||
|
||
/// Builds the "shell" for /shell1 | ||
class ScaffoldForShell1 extends StatelessWidget { | ||
/// Constructs an [ScaffoldForShell1]. | ||
const ScaffoldForShell1({ | ||
required this.child, | ||
super.key, | ||
}); | ||
|
||
/// The widget to display in the body of the Scaffold. | ||
/// In this sample, it is a Navigator. | ||
final Widget child; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar(title: const Text('shell1')), | ||
body: child, | ||
); | ||
} | ||
} | ||
|
||
/// Builds the "shell" for /shell1 | ||
class ScaffoldForShell2 extends StatelessWidget { | ||
/// Constructs an [ScaffoldForShell1]. | ||
const ScaffoldForShell2({ | ||
required this.child, | ||
super.key, | ||
}); | ||
|
||
/// The widget to display in the body of the Scaffold. | ||
/// In this sample, it is a Navigator. | ||
final Widget child; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar(title: const Text('shell2')), | ||
body: child, | ||
); | ||
} | ||
} | ||
|
||
/// The screen for /home | ||
class Home extends StatelessWidget { | ||
/// Constructs a [Home] widget. | ||
const Home({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Center( | ||
child: Column( | ||
mainAxisSize: MainAxisSize.min, | ||
children: <Widget>[ | ||
TextButton( | ||
onPressed: () { | ||
GoRouter.of(context).push('/shell1'); | ||
}, | ||
child: const Text('push the same shell route /shell1'), | ||
), | ||
TextButton( | ||
onPressed: () { | ||
GoRouter.of(context).push('/shell2'); | ||
}, | ||
child: const Text('push the different shell route /shell2'), | ||
), | ||
TextButton( | ||
onPressed: () { | ||
GoRouter.of(context).push('/regular-route'); | ||
}, | ||
child: const Text('push the regular route /regular-route'), | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
packages/go_router/example/test/push_with_shell_route_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// 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/go_router.dart'; | ||
import 'package:go_router_examples/push_with_shell_route.dart' as example; | ||
|
||
void main() { | ||
testWidgets('example works', (WidgetTester tester) async { | ||
await tester.pumpWidget(example.PushWithShellRouteExampleApp()); | ||
expect(find.text('shell1'), findsOneWidget); | ||
|
||
await tester.tap(find.text('push the same shell route /shell1')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsOneWidget); | ||
expect(find.text('shell1 body'), findsOneWidget); | ||
|
||
find.text('shell1 body').evaluate().first.pop(); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsOneWidget); | ||
expect(find.text('shell1 body'), findsNothing); | ||
|
||
await tester.tap(find.text('push the different shell route /shell2')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsNothing); | ||
expect(find.text('shell2'), findsOneWidget); | ||
expect(find.text('shell2 body'), findsOneWidget); | ||
|
||
find.text('shell2 body').evaluate().first.pop(); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsOneWidget); | ||
expect(find.text('shell2'), findsNothing); | ||
|
||
await tester.tap(find.text('push the regular route /regular-route')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsNothing); | ||
expect(find.text('regular route'), findsOneWidget); | ||
|
||
find.text('regular route').evaluate().first.pop(); | ||
await tester.pumpAndSettle(); | ||
expect(find.text('shell1'), findsOneWidget); | ||
expect(find.text('regular route'), findsNothing); | ||
}); | ||
} |
Oops, something went wrong.