diff --git a/mobile/lib/features/search/search_page.dart b/mobile/lib/features/search/search_page.dart index 48607d97f3..7bfa577247 100644 --- a/mobile/lib/features/search/search_page.dart +++ b/mobile/lib/features/search/search_page.dart @@ -101,6 +101,16 @@ class SearchPage extends HookConsumerWidget { void activateSearch() => focusNode.requestFocus(); + // Opening search as its own route means the user wants to type, so raise + // the keyboard right away instead of waiting for a tap on the field. + useEffect(() { + if (embedded) return null; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) focusNode.requestFocus(); + }); + return null; + }, const []); + useEffect(() { final reselection = tabReselection; if (reselection == null) return null; diff --git a/mobile/test/features/search/search_page_test.dart b/mobile/test/features/search/search_page_test.dart index 6aac4a4eb9..4fa4b6c964 100644 --- a/mobile/test/features/search/search_page_test.dart +++ b/mobile/test/features/search/search_page_test.dart @@ -252,7 +252,7 @@ void main() { debugDefaultTargetPlatformOverride = null; }); - testWidgets('X dismisses search while the keyboard is focused', ( + testWidgets('opening search focuses the field; X dismisses it', ( tester, ) async { await tester.pumpWidget( @@ -278,8 +278,9 @@ void main() { ); await tester.tap(find.text('Open search')); await tester.pumpAndSettle(); - await tester.tap(find.byType(TextField)); - await tester.pumpAndSettle(); + final field = tester.widget(find.byType(TextField)); + expect(field.focusNode!.hasFocus, isTrue); + expect(tester.testTextInput.isVisible, isTrue); await tester.enterText(find.byType(TextField), 'draft'); await tester.tap(find.byTooltip('Close search')); await tester.pumpAndSettle();