flutter_hooks now has useOnListenableChange

This commit is contained in:
Fabian Freund
2026-01-04 10:54:09 +01:00
parent 77657ffd2d
commit 65e8c2c323
14 changed files with 16 additions and 28 deletions
@@ -27,7 +27,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/features/bangs/domain/providers/search.dart';
import 'package:weblibre/features/bangs/presentation/widgets/bang_details.dart';
import 'package:weblibre/features/user/domain/providers.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
class BangSearchScreen extends HookConsumerWidget {
@@ -45,7 +44,7 @@ class BangSearchScreen extends HookConsumerWidget {
text: initialSearchText,
);
useListenableCallback(textEditingController, () {
useOnListenableChange(textEditingController, () {
unawaited(
ref
.read(bangSearchProvider.notifier)
@@ -34,7 +34,6 @@ import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/b
import 'package:weblibre/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/hooks/menu_controller.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
@@ -54,7 +53,7 @@ class BookmarkListScreen extends HookConsumerWidget {
final textFilterEnabled = useState(false);
final textFilterController = useTextEditingController();
useListenableCallback(textFilterController, () {
useOnListenableChange(textFilterController, () {
if (ref.exists(seamlessBookmarksProvider(entryGuid))) {
ref
.read(seamlessBookmarksProvider(entryGuid).notifier)
@@ -25,7 +25,6 @@ import 'package:nullability/nullability.dart';
import 'package:weblibre/features/bangs/domain/providers/bangs.dart';
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/auto_suggest_text_field.dart';
import 'package:weblibre/utils/uri_parser.dart' as uri_parser;
@@ -49,7 +48,7 @@ class AddressWithSuggestionsField extends HookConsumerWidget {
final suggestion = useState<String?>(null);
final lastText = useRef<String>(addressTextController.text);
useListenableCallback(addressTextController, () async {
useOnListenableChange(addressTextController, () async {
if (addressTextController.text.isNotEmpty) {
if (suggestion.value.isNotEmpty &&
lastText.value.length > 1 &&
@@ -27,7 +27,6 @@ import 'package:weblibre/features/bangs/presentation/widgets/site_search.dart';
import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/certificate_tile.dart';
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/draggable_scrollable_header.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/website_title_tile.dart';
class ClampingScrollPhysicsWithoutImplicit extends ClampingScrollPhysics {
@@ -100,7 +99,7 @@ class ViewTabSheetWidget extends HookConsumerWidget {
}
}
useListenableCallback(searchTextController, () {
useOnListenableChange(searchTextController, () {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await scroll();
});
@@ -22,7 +22,6 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/ta
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_chips.dart';
import 'package:weblibre/features/tor/presentation/controllers/start_tor_proxy.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/hooks/menu_controller.dart';
import 'package:weblibre/presentation/widgets/speech_to_text_button.dart';
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
@@ -55,7 +54,7 @@ class TabViewHeader extends HookConsumerWidget {
),
);
useListenableCallback(searchTextController, () async {
useOnListenableChange(searchTextController, () async {
if (ref.exists(tabSearchRepositoryProvider(TabSearchPartition.preview))) {
await ref
.read(
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:nullability/nullability.dart';
import 'package:weblibre/core/routing/routes.dart';
@@ -25,7 +26,6 @@ import 'package:weblibre/features/bangs/data/models/bang_data.dart';
import 'package:weblibre/features/bangs/data/models/bang_key.dart';
import 'package:weblibre/features/bangs/domain/providers/search.dart';
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
@@ -74,7 +74,7 @@ class BangChips extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final availableBangs = ref.watch(seamlessBangProvider);
useListenableCallback(searchTextController, () {
useOnListenableChange(searchTextController, () {
ref
.read(seamlessBangProvider.notifier)
.search(searchTextController!.text);
@@ -24,7 +24,6 @@ import 'package:nullability/nullability.dart';
import 'package:weblibre/features/bangs/data/models/bang_data.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
import 'package:weblibre/features/user/domain/providers.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/auto_suggest_text_field.dart';
import 'package:weblibre/presentation/widgets/speech_to_text_button.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
@@ -73,7 +72,7 @@ class SearchField extends HookConsumerWidget {
final lastText = useRef<String>(textEditingController.text);
if (showSuggestions) {
useListenableCallback(textEditingController, () async {
useOnListenableChange(textEditingController, () async {
if (textEditingController.text.isNotEmpty) {
if (suggestion.value.isNotEmpty &&
lastText.value.length > 1 &&
@@ -19,6 +19,7 @@
*/
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:nullability/nullability.dart';
import 'package:skeletonizer/skeletonizer.dart';
@@ -31,7 +32,6 @@ import 'package:weblibre/features/web_feed/data/models/feed_link.dart';
import 'package:weblibre/features/web_feed/domain/providers.dart';
import 'package:weblibre/features/web_feed/extensions/atom.dart';
import 'package:weblibre/features/web_feed/extensions/feed_article.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
import 'package:weblibre/utils/text_highlight.dart';
@@ -50,7 +50,7 @@ class FeedSearch extends HookConsumerWidget {
final articlesAsync = ref.watch(articleSearchProvider(null));
useListenableCallback(searchTextNotifier, () async {
useOnListenableChange(searchTextNotifier, () async {
await ref
.read(articleSearchProvider(null).notifier)
.search(
@@ -25,7 +25,6 @@ import 'package:nullability/nullability.dart';
import 'package:weblibre/extensions/uri.dart';
import 'package:weblibre/features/bangs/data/models/bang_data.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/search_suggestions.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/utils/uri_parser.dart' as uri_parser;
class FixedSearchTermSuggestions extends HookConsumerWidget {
@@ -60,7 +59,7 @@ class FixedSearchTermSuggestions extends HookConsumerWidget {
final searchSuggestions = ref.watch(searchSuggestionsProvider());
useListenableCallback(searchTextController, () {
useOnListenableChange(searchTextController, () {
if (ref.exists(searchSuggestionsProvider())) {
ref
.read(searchSuggestionsProvider().notifier)
@@ -30,7 +30,6 @@ import 'package:weblibre/features/bangs/domain/repositories/data.dart';
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/search_suggestions.dart';
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/bang_chips.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
class FullSearchTermSuggestions extends HookConsumerWidget {
final TextEditingController searchTextController;
@@ -55,7 +54,7 @@ class FullSearchTermSuggestions extends HookConsumerWidget {
final searchHistory = ref.watch(searchHistoryProvider);
useListenableCallback(searchTextController, () {
useOnListenableChange(searchTextController, () {
ref
.read(searchSuggestionsProvider().notifier)
.addQuery(searchTextController.text);
@@ -31,7 +31,6 @@ import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
import 'package:weblibre/features/geckoview/utils/image_helper.dart';
import 'package:weblibre/presentation/hooks/cached_future.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
@@ -49,7 +48,7 @@ class HistorySuggestions extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final historySuggestionsAsync = ref.watch(engineHistorySuggestionsProvider);
useListenableCallback(searchTextListenable, () async {
useOnListenableChange(searchTextListenable, () async {
if (ref.exists(engineSuggestionsProvider)) {
await ref
.watch(engineSuggestionsProvider.notifier)
@@ -39,7 +39,6 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/providers/selec
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab_search.dart';
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_chips.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
import 'package:weblibre/utils/text_highlight.dart';
@@ -106,7 +105,7 @@ class TabSearch extends HookConsumerWidget {
}),
);
useListenableCallback(searchTextListenable, () async {
useOnListenableChange(searchTextListenable, () async {
if (ref.exists(tabSearchRepositoryProvider(TabSearchPartition.search))) {
await ref
.read(
@@ -26,7 +26,6 @@ import 'package:weblibre/features/web_feed/domain/providers.dart';
import 'package:weblibre/features/web_feed/domain/providers/article_filter.dart';
import 'package:weblibre/features/web_feed/presentation/controllers/fetch_articles.dart';
import 'package:weblibre/features/web_feed/presentation/widgets/feed_article_card.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
import 'package:weblibre/presentation/widgets/speech_to_text_button.dart';
@@ -57,7 +56,7 @@ class FeedArticleListScreen extends HookConsumerWidget {
() => searchTextController.text.isNotEmpty,
);
useListenableCallback(searchTextController, () {
useOnListenableChange(searchTextController, () {
ref
.read(filteredArticleListProvider(feedId).notifier)
.search(searchTextController.text);
@@ -20,7 +20,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
final _tagSplitPatter = RegExp(r'[,\s]+');
@@ -39,7 +38,7 @@ class TagField extends HookWidget {
final textController = useTextEditingController();
final tags = useState(initialTags);
useListenableCallback(tags, () {
useOnListenableChange(tags, () {
onTagsUpdate(tags.value);
});