fix: add parameter to maintainState of SearchDelegate (#152444)

Add parameter to `showSearch`, which is passed to `_SearchPageRoute` to maintain the state of the SearchDelegate.

- fix #43582

_Just contributed this change to start the conversation on how the #43582 can be addressed. Have not added tests yet._
This commit is contained in:
Gazal 2024-08-07 03:53:03 +10:00 committed by GitHub
parent a9b2d8d6d4
commit 6f98b485ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 3 deletions

View File

@ -48,6 +48,10 @@ import 'theme.dart';
/// route created by this method is pushed to the nearest navigator to the
/// given `context`. It can not be `null`.
///
/// The `maintainState` argument is used to determine if the route should remain
/// in memory when it is inactive (see [ModalRoute.maintainState] for more details].
/// By default, `maintainState` is `false`.
///
/// The transition to the search page triggered by this method looks best if the
/// screen triggering the transition contains an [AppBar] at the top and the
/// transition is called from an [IconButton] that's part of [AppBar.actions].
@ -68,11 +72,13 @@ Future<T?> showSearch<T>({
required SearchDelegate<T> delegate,
String? query = '',
bool useRootNavigator = false,
bool maintainState = false,
}) {
delegate.query = query ?? delegate.query;
delegate._currentBody = _SearchBody.suggestions;
return Navigator.of(context, rootNavigator: useRootNavigator).push(_SearchPageRoute<T>(
delegate: delegate,
maintainState: maintainState
));
}
@ -417,6 +423,7 @@ enum _SearchBody {
class _SearchPageRoute<T> extends PageRoute<T> {
_SearchPageRoute({
required this.delegate,
required this.maintainState,
}) {
assert(
delegate._route == null,
@ -429,6 +436,9 @@ class _SearchPageRoute<T> extends PageRoute<T> {
final SearchDelegate<T> delegate;
@override
final bool maintainState;
@override
Color? get barrierColor => null;
@ -438,9 +448,6 @@ class _SearchPageRoute<T> extends PageRoute<T> {
@override
Duration get transitionDuration => const Duration(milliseconds: 300);
@override
bool get maintainState => false;
@override
Widget buildTransitions(
BuildContext context,

View File

@ -1175,6 +1175,63 @@ void main() {
await tester.pump();
expect(textField.controller!.text.length, 15);
}, skip: kIsWeb); // [intended] We do not use Flutter-rendered context menu on the Web.
testWidgets('showSearch with maintainState on the route', (WidgetTester tester) async {
final _MyNavigatorObserver navigationObserver = _MyNavigatorObserver();
final _TestEmptySearchDelegate delegate = _TestEmptySearchDelegate();
addTearDown(delegate.dispose);
await tester.pumpWidget(MaterialApp(
navigatorObservers: <NavigatorObserver>[navigationObserver],
home: Builder(builder: (BuildContext context) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () async {
await showSearch(
context: context,
delegate: delegate,
);
},
child: const Text('showSearch'),
),
TextButton(
onPressed: () async {
await showSearch(
context: context,
delegate: delegate,
maintainState: true,
);
},
child: const Text('showSearchWithMaintainState'),
),
],
)),
));
expect(navigationObserver.pushCount, 0);
expect(navigationObserver.maintainState, false);
// showSearch normal and back.
await tester.tap(find.text('showSearch'));
await tester.pumpAndSettle();
final Finder backButtonFinder = find.byType(BackButton);
expect(backButtonFinder, findsWidgets);
await tester.tap(find.byTooltip('Close'));
await tester.pumpAndSettle();
expect(navigationObserver.pushCount, 1);
expect(navigationObserver.maintainState, false);
// showSearch with maintainState.
await tester.tap(find.text('showSearchWithMaintainState'));
await tester.pumpAndSettle();
expect(backButtonFinder, findsWidgets);
await tester.tap(find.byTooltip('Close'));
await tester.pumpAndSettle();
expect(navigationObserver.pushCount, 2);
expect(navigationObserver.maintainState, true);
});
}
class TestHomePage extends StatelessWidget {
@ -1358,6 +1415,7 @@ class _TestEmptySearchDelegate extends SearchDelegate<String> {
}
class _MyNavigatorObserver extends NavigatorObserver {
bool maintainState = false;
int pushCount = 0;
@override
@ -1366,6 +1424,9 @@ class _MyNavigatorObserver extends NavigatorObserver {
if (<String>['nested', '/'].contains(route.settings.name)) {
return;
}
if (route is PageRoute) {
maintainState = route.maintainState;
}
pushCount++;
}
}