mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
fix route annoucement for first route and last route (#57339)
This commit is contained in:
parent
e05a67f068
commit
7e2f555d1b
|
@ -2293,6 +2293,12 @@ enum _RouteLifecycle {
|
|||
|
||||
typedef _RouteEntryPredicate = bool Function(_RouteEntry entry);
|
||||
|
||||
class _NotAnnounced extends Route<void> {
|
||||
// A placeholder for the lastAnnouncedPreviousRoute, the
|
||||
// lastAnnouncedPoppedNextRoute, and the lastAnnouncedNextRoute before any
|
||||
// change has been announced.
|
||||
}
|
||||
|
||||
class _RouteEntry extends RouteTransitionRecord {
|
||||
_RouteEntry(
|
||||
this.route, {
|
||||
|
@ -2311,10 +2317,12 @@ class _RouteEntry extends RouteTransitionRecord {
|
|||
@override
|
||||
final Route<dynamic> route;
|
||||
|
||||
static Route<dynamic> notAnnounced = _NotAnnounced();
|
||||
|
||||
_RouteLifecycle currentState;
|
||||
Route<dynamic> lastAnnouncedPreviousRoute; // last argument to Route.didChangePrevious
|
||||
Route<dynamic> lastAnnouncedPoppedNextRoute; // last argument to Route.didPopNext
|
||||
Route<dynamic> lastAnnouncedNextRoute; // last argument to Route.didChangeNext
|
||||
Route<dynamic> lastAnnouncedPreviousRoute = notAnnounced; // last argument to Route.didChangePrevious
|
||||
Route<dynamic> lastAnnouncedPoppedNextRoute = notAnnounced; // last argument to Route.didPopNext
|
||||
Route<dynamic> lastAnnouncedNextRoute = notAnnounced; // last argument to Route.didChangeNext
|
||||
|
||||
bool get hasPage => route.settings is Page;
|
||||
|
||||
|
|
|
@ -1840,6 +1840,57 @@ void main() {
|
|||
expect(tickCount, 4);
|
||||
});
|
||||
|
||||
testWidgets('Route annouce correctly for first route and last route', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/57133.
|
||||
Route<void> previousOfFirst = NotAnnounced();
|
||||
Route<void> nextOfFirst = NotAnnounced();
|
||||
Route<void> popNextOfFirst = NotAnnounced();
|
||||
Route<void> firstRoute;
|
||||
|
||||
Route<void> previousOfSecond = NotAnnounced();
|
||||
Route<void> nextOfSecond = NotAnnounced();
|
||||
Route<void> popNextOfSecond = NotAnnounced();
|
||||
Route<void> secondRoute;
|
||||
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
navigatorKey: navigator,
|
||||
initialRoute: '/second',
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
if (settings.name == '/') {
|
||||
firstRoute = RouteAnnouncementSpy(
|
||||
onDidChangeNext: (Route<void> next) => nextOfFirst = next,
|
||||
onDidChangePrevious: (Route<void> previous) => previousOfFirst = previous,
|
||||
onDidPopNext: (Route<void> next) => popNextOfFirst = next,
|
||||
settings: settings,
|
||||
);
|
||||
return firstRoute;
|
||||
}
|
||||
secondRoute = RouteAnnouncementSpy(
|
||||
onDidChangeNext: (Route<void> next) => nextOfSecond = next,
|
||||
onDidChangePrevious: (Route<void> previous) => previousOfSecond = previous,
|
||||
onDidPopNext: (Route<void> next) => popNextOfSecond = next,
|
||||
settings: settings,
|
||||
);
|
||||
return secondRoute;
|
||||
},
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(previousOfFirst, isNull);
|
||||
expect(nextOfFirst, secondRoute);
|
||||
expect(popNextOfFirst, isA<NotAnnounced>());
|
||||
|
||||
expect(previousOfSecond, firstRoute);
|
||||
expect(nextOfSecond, isNull);
|
||||
expect(popNextOfSecond, isA<NotAnnounced>());
|
||||
|
||||
navigator.currentState.pop();
|
||||
expect(popNextOfFirst, secondRoute);
|
||||
});
|
||||
|
||||
group('Page api', (){
|
||||
Widget buildNavigator(
|
||||
List<Page<dynamic>> pages,
|
||||
|
@ -2561,6 +2612,50 @@ void main() {
|
|||
});
|
||||
}
|
||||
|
||||
typedef AnnouncementCallBack = void Function(Route<dynamic>);
|
||||
|
||||
class NotAnnounced extends Route<void> {/* A place holder for not announced route*/}
|
||||
|
||||
class RouteAnnouncementSpy extends Route<void> {
|
||||
RouteAnnouncementSpy({
|
||||
this.onDidChangePrevious,
|
||||
this.onDidChangeNext,
|
||||
this.onDidPopNext,
|
||||
RouteSettings settings,
|
||||
}) : super(settings: settings);
|
||||
final AnnouncementCallBack onDidChangePrevious;
|
||||
final AnnouncementCallBack onDidChangeNext;
|
||||
final AnnouncementCallBack onDidPopNext;
|
||||
|
||||
@override
|
||||
List<OverlayEntry> get overlayEntries => <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
builder: (BuildContext context) => const Placeholder(),
|
||||
)
|
||||
];
|
||||
|
||||
@override
|
||||
void didChangeNext(Route<dynamic> nextRoute) {
|
||||
super.didChangeNext(nextRoute);
|
||||
if (onDidChangeNext != null)
|
||||
onDidChangeNext(nextRoute);
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangePrevious(Route<dynamic> previousRoute) {
|
||||
super.didChangePrevious(previousRoute);
|
||||
if (onDidChangePrevious != null)
|
||||
onDidChangePrevious(previousRoute);
|
||||
}
|
||||
|
||||
@override
|
||||
void didPopNext(Route<dynamic> nextRoute) {
|
||||
super.didPopNext(nextRoute);
|
||||
if (onDidPopNext != null)
|
||||
onDidPopNext(nextRoute);
|
||||
}
|
||||
}
|
||||
|
||||
class _TickingWidget extends StatefulWidget {
|
||||
const _TickingWidget({this.onTick});
|
||||
|
||||
|
|
Loading…
Reference in a new issue