Unverified Commit 06140f2b authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Closing search with system back button works (#18174)

Fixes #18145.
parent 0a26ac09
...@@ -26,8 +26,9 @@ import 'theme.dart'; ...@@ -26,8 +26,9 @@ import 'theme.dart';
/// to the empty string. When `query` is set to null, `delegate.query` will /// to the empty string. When `query` is set to null, `delegate.query` will
/// be used as the initial query. /// be used as the initial query.
/// ///
/// The method returns the selected search result, which can be set in the /// This method returns the selected search result, which can be set in the
/// [SearchDelegate.close] call. /// [SearchDelegate.close] call. If the search page is closed with the system
/// back button, it returns null.
/// ///
/// A given [SearchDelegate] can only be associated with one active [showSearch] /// A given [SearchDelegate] can only be associated with one active [showSearch]
/// call. Call [SearchDelegate.close] before re-using the same delegate instance /// call. Call [SearchDelegate.close] before re-using the same delegate instance
...@@ -52,14 +53,11 @@ Future<T> showSearch<T>({ ...@@ -52,14 +53,11 @@ Future<T> showSearch<T>({
}) { }) {
assert(delegate != null); assert(delegate != null);
assert(context != null); assert(context != null);
assert(delegate._result == null || delegate._result.isCompleted);
delegate._result = new Completer<T>();
delegate.query = query ?? delegate.query; delegate.query = query ?? delegate.query;
delegate._currentBody = _SearchBody.suggestions; delegate._currentBody = _SearchBody.suggestions;
Navigator.of(context).push(new _SearchPageRoute<T>( return Navigator.of(context).push(new _SearchPageRoute<T>(
delegate: delegate, delegate: delegate,
)); ));
return delegate._result.future;
} }
/// Delegate for [showSearch] to define the content of the search page. /// Delegate for [showSearch] to define the content of the search page.
...@@ -215,7 +213,6 @@ abstract class SearchDelegate<T> { ...@@ -215,7 +213,6 @@ abstract class SearchDelegate<T> {
void close(BuildContext context, T result) { void close(BuildContext context, T result) {
_currentBody = null; _currentBody = null;
_focusNode.unfocus(); _focusNode.unfocus();
_result.complete(result);
Navigator.of(context) Navigator.of(context)
..popUntil((Route<dynamic> route) => route == _route) ..popUntil((Route<dynamic> route) => route == _route)
..pop(result); ..pop(result);
...@@ -242,8 +239,6 @@ abstract class SearchDelegate<T> { ...@@ -242,8 +239,6 @@ abstract class SearchDelegate<T> {
_currentBodyNotifier.value = value; _currentBodyNotifier.value = value;
} }
Completer<T> _result;
_SearchPageRoute<T> _route; _SearchPageRoute<T> _route;
} }
...@@ -263,7 +258,7 @@ enum _SearchBody { ...@@ -263,7 +258,7 @@ enum _SearchBody {
} }
class _SearchPageRoute<T> extends PageRoute<void> { class _SearchPageRoute<T> extends PageRoute<T> {
_SearchPageRoute({ _SearchPageRoute({
@required this.delegate, @required this.delegate,
}) : assert(delegate != null) { }) : assert(delegate != null) {
...@@ -323,10 +318,11 @@ class _SearchPageRoute<T> extends PageRoute<void> { ...@@ -323,10 +318,11 @@ class _SearchPageRoute<T> extends PageRoute<void> {
} }
@override @override
void didComplete(void result) { void didComplete(T result) {
super.didComplete(result); super.didComplete(result);
assert(delegate._route == this); assert(delegate._route == this);
delegate._route = null; delegate._route = null;
delegate._currentBody = null;
} }
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
...@@ -42,6 +43,51 @@ void main() { ...@@ -42,6 +43,51 @@ void main() {
expect(selectedResults, <String>['Result']); expect(selectedResults, <String>['Result']);
}); });
testWidgets('Can close search with system back button to return null', (WidgetTester tester) async {
// regression test for https://github.com/flutter/flutter/issues/18145
final _TestSearchDelegate delegate = new _TestSearchDelegate();
final List<String> selectedResults = <String>[];
await tester.pumpWidget(new TestHomePage(
delegate: delegate,
results: selectedResults,
));
// We are on the homepage
expect(find.text('HomeBody'), findsOneWidget);
expect(find.text('HomeTitle'), findsOneWidget);
expect(find.text('Suggestions'), findsNothing);
// Open search
await tester.tap(find.byTooltip('Search'));
await tester.pumpAndSettle();
expect(find.text('HomeBody'), findsNothing);
expect(find.text('HomeTitle'), findsNothing);
expect(find.text('Suggestions'), findsOneWidget);
// Simulate system back button
final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute'));
await BinaryMessages.handlePlatformMessage('flutter/navigation', message, (_) {});
await tester.pumpAndSettle();
expect(selectedResults, <void>[null]);
// We are on the homepage again
expect(find.text('HomeBody'), findsOneWidget);
expect(find.text('HomeTitle'), findsOneWidget);
expect(find.text('Suggestions'), findsNothing);
// Open search again
await tester.tap(find.byTooltip('Search'));
await tester.pumpAndSettle();
expect(find.text('HomeBody'), findsNothing);
expect(find.text('HomeTitle'), findsNothing);
expect(find.text('Suggestions'), findsOneWidget);
});
testWidgets('Requests suggestions', (WidgetTester tester) async { testWidgets('Requests suggestions', (WidgetTester tester) async {
final _TestSearchDelegate delegate = new _TestSearchDelegate(); final _TestSearchDelegate delegate = new _TestSearchDelegate();
...@@ -414,7 +460,7 @@ void main() { ...@@ -414,7 +460,7 @@ void main() {
expect(find.text('HomeBody'), findsOneWidget); expect(find.text('HomeBody'), findsOneWidget);
expect(find.text('Suggestions'), findsNothing); expect(find.text('Suggestions'), findsNothing);
expect(find.text('Nested Suggestions'), findsNothing); expect(find.text('Nested Suggestions'), findsNothing);
expect(nestedSearchResults, hasLength(0)); expect(nestedSearchResults, <String>[null]);
expect(selectedResults, <String>['Result Foo']); expect(selectedResults, <String>['Result Foo']);
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment