diff --git a/app/lib/features/bangs/presentation/widgets/site_search.dart b/app/lib/features/bangs/presentation/widgets/site_search.dart
index 3d5cc3e3..6511ac34 100644
--- a/app/lib/features/bangs/presentation/widgets/site_search.dart
+++ b/app/lib/features/bangs/presentation/widgets/site_search.dart
@@ -17,6 +17,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
+import 'dart:async';
+
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -35,7 +37,7 @@ import 'package:weblibre/features/geckoview/features/search/domain/providers/sea
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/search_field.dart';
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/search_modules/fixed_search_suggestions.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
-import 'package:weblibre/presentation/hooks/listenable_callback.dart';
+import 'package:weblibre/presentation/hooks/on_listenable_change_selector.dart';
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
import 'package:weblibre/utils/uri_parser.dart' as uri_parser;
@@ -59,7 +61,52 @@ class SiteSearch extends HookConsumerWidget {
final searchTextController = controller ?? useTextEditingController();
final searchFocusNode = useFocusNode();
- useListenableCallback(searchTextController, () {
+ useOnListenableChangeSelector(
+ searchFocusNode,
+ () => searchFocusNode.hasFocus,
+ () {
+ if (searchFocusNode.hasFocus) {
+ // Select all text when the field is focused
+ searchTextController.selection = TextSelection(
+ baseOffset: 0,
+ extentOffset: searchTextController.text.length,
+ );
+ }
+ },
+ );
+
+ //Request initial focus in a way our useOnListenableChangeSelector is triggered
+ useEffect(() {
+ //Wait for first frame then request focus
+ unawaited(
+ Future.delayed(const Duration(milliseconds: 1000 ~/ 60)).whenComplete(
+ () {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ searchFocusNode.requestFocus();
+ });
+ },
+ ),
+ );
+
+ return null;
+ }, []);
+
+ useOnAppLifecycleStateChange((previous, current) {
+ switch (current) {
+ case AppLifecycleState.detached:
+ case AppLifecycleState.inactive:
+ case AppLifecycleState.hidden:
+ case AppLifecycleState.paused:
+ //Fixes issue with disappearing keyboard after resume (even we request focus)
+ searchFocusNode.unfocus();
+ case AppLifecycleState.resumed:
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ searchFocusNode.requestFocus();
+ });
+ }
+ });
+
+ useOnListenableChange(searchTextController, () {
if (ref.exists(searchSuggestionsProvider())) {
ref
.read(searchSuggestionsProvider().notifier)
@@ -171,15 +218,6 @@ class SiteSearch extends HookConsumerWidget {
label: (selectedBang != null)
? const Text('Search')
: const Text('Address / Search'),
- onTap: () {
- if (!searchFocusNode.hasFocus) {
- // Select all text when the field is tapped
- searchTextController.selection = TextSelection(
- baseOffset: 0,
- extentOffset: searchTextController.text.length,
- );
- }
- },
unfocusOnTapOutside: false,
onSubmitted: (value) async {
await submitSearch(value);
diff --git a/app/lib/presentation/hooks/listenable_callback.dart b/app/lib/presentation/hooks/listenable_callback.dart
deleted file mode 100644
index c4f90eb9..00000000
--- a/app/lib/presentation/hooks/listenable_callback.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2024-2025 Fabian Freund.
- *
- * This file is part of WebLibre
- * (see https://weblibre.eu).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-import 'package:flutter/foundation.dart';
-import 'package:flutter_hooks/flutter_hooks.dart';
-
-void useListenableCallback(
- Listenable? listenable,
- void Function() callback, [
- List