diff --git a/analysis_options.yaml b/analysis_options.yaml index 0f775d6f..2d3bf859 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -11,6 +11,7 @@ linter: analyzer: errors: + avoid_redundant_argument_values: ignore experimental_member_use: ignore exclude: - "**.g.dart" diff --git a/apps/weblibre/lib/domain/services/generic_website.dart b/apps/weblibre/lib/domain/services/generic_website.dart index 571fece7..7d19a821 100644 --- a/apps/weblibre/lib/domain/services/generic_website.dart +++ b/apps/weblibre/lib/domain/services/generic_website.dart @@ -17,6 +17,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +import 'dart:async'; import 'dart:io'; import 'dart:ui'; @@ -193,7 +194,7 @@ class GenericWebsiteService extends _$GenericWebsiteService { inFlight = _fetchAndCacheDdgIcon(url, cacheMissing: cacheMissing) .whenComplete(() { if (identical(_inFlightIconFetches[origin], inFlight)) { - _inFlightIconFetches.remove(origin); + _inFlightIconFetches.remove(origin)?.ignore(); } }); diff --git a/apps/weblibre/lib/features/account/data/models/account_auth_state.dart b/apps/weblibre/lib/features/account/data/models/account_auth_state.dart index 0767b422..9a3b5676 100644 --- a/apps/weblibre/lib/features/account/data/models/account_auth_state.dart +++ b/apps/weblibre/lib/features/account/data/models/account_auth_state.dart @@ -37,7 +37,6 @@ class AccountAuthState with FastEquatable { // states for the same user but with distinct client instances are still // semantically equal — including identityHashCode here would defeat // Riverpod's caching by treating every reissued state as different. - // ignore: missing_field_in_equatable_props final SupabaseClient? client; AccountAuthState({ @@ -64,5 +63,6 @@ class AccountAuthState with FastEquatable { userId, lastError, syncKey, + client, ]; } diff --git a/apps/weblibre/lib/features/account/domain/repositories/account_auth.dart b/apps/weblibre/lib/features/account/domain/repositories/account_auth.dart index e8417671..bc2fb2ae 100644 --- a/apps/weblibre/lib/features/account/domain/repositories/account_auth.dart +++ b/apps/weblibre/lib/features/account/domain/repositories/account_auth.dart @@ -271,7 +271,6 @@ class AccountAuthRepository extends _$AccountAuthRepository { // Clear the pending code verifier so a late browser callback is rejected. final data = await _store.read(); - // ignore: avoid_redundant_argument_values await _store.write(data.copyWith(pendingCodeVerifier: null)); state = AsyncData(AccountAuthState()); @@ -327,7 +326,6 @@ class AccountAuthRepository extends _$AccountAuthRepository { displayName: (user?['user_metadata'] as Map?)?['display_name'] as String?, - // ignore: avoid_redundant_argument_values pendingCodeVerifier: null, ), ); @@ -372,9 +370,7 @@ class AccountAuthRepository extends _$AccountAuthRepository { Future clearSyncKey() async { final data = await _store.read(); - // ignore: avoid_redundant_argument_values await _store.write(data.copyWith(syncKey: null)); - // ignore: avoid_redundant_argument_values state = AsyncData(_currentOrEmpty.copyWith(syncKey: null)); } diff --git a/apps/weblibre/lib/features/bangs/data/models/web_search_bang.dart b/apps/weblibre/lib/features/bangs/data/models/web_search_bang.dart index 5bc87ac3..d8d71aea 100644 --- a/apps/weblibre/lib/features/bangs/data/models/web_search_bang.dart +++ b/apps/weblibre/lib/features/bangs/data/models/web_search_bang.dart @@ -15,7 +15,7 @@ final webSearchBang = BangData( searxngApi: false, ); -final webSearchBangKey = BangKey( +const webSearchBangKey = BangKey( group: BangGroup.weblibre, trigger: webSearchBangTrigger, ); diff --git a/apps/weblibre/lib/features/bangs/presentation/screens/search.dart b/apps/weblibre/lib/features/bangs/presentation/screens/search.dart index 435ac272..aafc9026 100644 --- a/apps/weblibre/lib/features/bangs/presentation/screens/search.dart +++ b/apps/weblibre/lib/features/bangs/presentation/screens/search.dart @@ -17,14 +17,12 @@ * 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:fading_scroll/fading_scroll.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:weblibre/features/bangs/data/models/bang_data.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'; diff --git a/apps/weblibre/lib/features/geckoview/features/browser/domain/providers.dart b/apps/weblibre/lib/features/geckoview/features/browser/domain/providers.dart index c0da2bae..bc69c27a 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/domain/providers.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/domain/providers.dart @@ -1033,7 +1033,7 @@ EquatableValue> groupedTabListItems( final unpinned = children .where((c) => !pinnedTabIds.contains(c.row.id)) .toList(); - final cmp = (_GroupedRow a, _GroupedRow b) => + int cmp(_GroupedRow a, _GroupedRow b) => a.row.orderKey.compareTo(b.row.orderKey); final directionCmp = tabListDirection == TabDirection.newestFirst ? (_GroupedRow a, _GroupedRow b) => -cmp(a, b) diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart index dd1032b9..f3cc281b 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart @@ -85,12 +85,10 @@ class TabViewFilterController extends _$TabViewFilterController { } void setDateRange(DateTimeRange? range) { - // ignore: avoid_redundant_argument_values state = state.copyWith(dateRange: range, quickInterval: null); } void setQuickInterval(TabQuickInterval? interval) { - // ignore: avoid_redundant_argument_values state = state.copyWith(quickInterval: interval, dateRange: null); } diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart index 8f3a5f06..9c7d6af1 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart @@ -1194,13 +1194,11 @@ class _Browser extends HookConsumerWidget { switch (promptOnBackBehavior) { case BackgroundAppTabBackPromptBehavior(): await moveToBackground(); - break; case ReturnToSearchTabBackPromptBehavior(:final tabType): ref .read(searchAutofocusSuppressionProvider.notifier) .suppressNext(); await SearchRoute(tabType: tabType).push(context); - break; } return true; diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/utils/tab_view_reorder.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/utils/tab_view_reorder.dart index 0e5cd3ac..eb0ef24b 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/utils/tab_view_reorder.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/utils/tab_view_reorder.dart @@ -219,7 +219,7 @@ List _orderedIdsForStorageAnchors( required String movingPartitionRootId, required bool sortPinnedFirst, }) { - var storageOrderedIds = tabListDirection == TabDirection.newestFirst + final storageOrderedIds = tabListDirection == TabDirection.newestFirst // Rendering flips root group order for newest-first; convert the // display order back to storage order before choosing anchors. ? orderedTabIds.reversed.toList() diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart index 80edf329..56797bbd 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart @@ -580,11 +580,13 @@ class QuickTabSwitcher extends HookConsumerWidget { WidgetsBinding.instance.addPostFrameCallback((_) { final context = activeItemKey.value.currentContext; if (context != null) { - Scrollable.ensureVisible( - context, - alignment: 0.5, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, + unawaited( + Scrollable.ensureVisible( + context, + alignment: 0.5, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + ), ); } else if (chipScrollController.hasClients) { final activeIndex = availableItems.indexWhere( @@ -602,11 +604,13 @@ class QuickTabSwitcher extends HookConsumerWidget { WidgetsBinding.instance.addPostFrameCallback((_) { final retryContext = activeItemKey.value.currentContext; if (retryContext != null) { - Scrollable.ensureVisible( - retryContext, - alignment: 0.5, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, + unawaited( + Scrollable.ensureVisible( + retryContext, + alignment: 0.5, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + ), ); } }); @@ -717,8 +721,6 @@ class QuickTabSwitcherView extends StatelessWidget { @override Widget build(BuildContext context) { final appColors = AppColors.of(context); - final colorScheme = Theme.of(context).colorScheme; - if (availableItems.isEmpty) { return const SizedBox.shrink(); } diff --git a/apps/weblibre/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart b/apps/weblibre/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart index 32bd8cae..a25b63b7 100644 --- a/apps/weblibre/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart +++ b/apps/weblibre/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart @@ -27,8 +27,8 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:rxdart/rxdart.dart'; import 'package:weblibre/core/logger.dart'; -import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_migrations.dart'; import 'package:weblibre/features/geckoview/features/preferences/data/models/preference_setting.dart'; +import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_migrations.dart'; import 'package:weblibre/features/geckoview/features/tabs/utils/setting_groups_serializer.dart'; import 'package:weblibre/features/user/data/providers.dart'; diff --git a/apps/weblibre/lib/features/geckoview/features/pwa/domain/providers.dart b/apps/weblibre/lib/features/geckoview/features/pwa/domain/providers.dart index 441e4986..322547f9 100644 --- a/apps/weblibre/lib/features/geckoview/features/pwa/domain/providers.dart +++ b/apps/weblibre/lib/features/geckoview/features/pwa/domain/providers.dart @@ -107,7 +107,7 @@ Future installCurrentWebApp( Ref ref, { String? overrideName, String? contextId, -}) async { +}) { final selectedTabId = ref.read(selectedTabProvider); if (selectedTabId == null) { @@ -156,7 +156,7 @@ Future installBasicShortcut( Ref ref, { String? overrideName, String? contextId, -}) async { +}) { final selectedTabId = ref.read(selectedTabProvider); if (selectedTabId == null) { diff --git a/apps/weblibre/lib/features/geckoview/features/search/presentation/screens/search.dart b/apps/weblibre/lib/features/geckoview/features/search/presentation/screens/search.dart index d17243cc..cd14f126 100644 --- a/apps/weblibre/lib/features/geckoview/features/search/presentation/screens/search.dart +++ b/apps/weblibre/lib/features/geckoview/features/search/presentation/screens/search.dart @@ -801,8 +801,8 @@ class _WebSearchOptionsRow extends StatelessWidget { controller: controller, scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8), - child: Row( - children: const [ + child: const Row( + children: [ WebSearchStatusChip(), RouteThroughTorToggle(), SizedBox(width: 8), diff --git a/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/feed_search.dart b/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/feed_search.dart index 1958ff37..fa118cdf 100644 --- a/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/feed_search.dart +++ b/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/feed_search.dart @@ -60,9 +60,7 @@ class FeedSearch extends HookConsumerWidget { .read(articleSearchProvider(null).notifier) .search( searchTextNotifier.value.text, - // ignore: avoid_redundant_argument_values dont break things matchPrefix: _matchPrefix, - // ignore: avoid_redundant_argument_values dont break things matchSuffix: _matchSuffix, ); }, diff --git a/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/tab_search.dart b/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/tab_search.dart index bd721833..f7919985 100644 --- a/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/tab_search.dart +++ b/apps/weblibre/lib/features/geckoview/features/search/presentation/widgets/search_modules/tab_search.dart @@ -123,9 +123,7 @@ class TabSearch extends HookConsumerWidget { ) .addQuery( searchTextListenable.value.text, - // ignore: avoid_redundant_argument_values dont break things matchPrefix: _matchPrefix, - // ignore: avoid_redundant_argument_values dont break things matchSuffix: _matchSuffix, ); } diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart index 4bf16c31..62e156c1 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart @@ -18,6 +18,8 @@ * along with this program. If not, see . */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; @@ -181,7 +183,7 @@ class ContainerEditScreen extends HookConsumerWidget { title: const Text('Change Color'), onTap: () { Navigator.of(context).pop(); - openColorPicker(); + unawaited(openColorPicker()); }, ), ListTile( @@ -189,7 +191,7 @@ class ContainerEditScreen extends HookConsumerWidget { title: const Text('Change Icon'), onTap: () { Navigator.of(context).pop(); - openIconPicker(); + unawaited(openIconPicker()); }, ), const SizedBox(height: 8), diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_list.dart b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_list.dart index 57769e3b..877b2b6c 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_list.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_list.dart @@ -105,7 +105,6 @@ class ContainerListScreen extends HookConsumerWidget { .read(selectedContainerProvider.notifier) .clearContainer() : () => setSelectedContainer(container), - // onDelete: () => repository.deleteContainer(container.id), ), ); }, @@ -168,7 +167,6 @@ class _ContainerCard extends HookConsumerWidget { required this.isSelected, required this.onTap, required this.onSelect, - this.onDelete, }); final ContainerDataWithCount container; @@ -176,7 +174,6 @@ class _ContainerCard extends HookConsumerWidget { final bool isSelected; final VoidCallback onTap; final VoidCallback onSelect; - final VoidCallback? onDelete; @override Widget build(BuildContext context, WidgetRef ref) { @@ -299,15 +296,6 @@ class _ContainerCard extends HookConsumerWidget { else const SizedBox.shrink(), const Spacer(), - if (onDelete != null) ...[ - IconButton( - tooltip: 'Delete', - color: colorScheme.error, - onPressed: onDelete, - icon: const Icon(Icons.delete_outline), - ), - const SizedBox(width: 4), - ], FilledButton.tonalIcon( onPressed: onSelect, icon: Icon(isSelected ? Icons.close : Icons.check), diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/compact_container_selector.dart b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/compact_container_selector.dart index cccdd1d7..b5388f96 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/compact_container_selector.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/compact_container_selector.dart @@ -20,9 +20,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:nullability/nullability.dart'; import 'package:weblibre/core/routing/routes.dart'; import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/entities/container_selection_result.dart'; diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/container_chips.dart b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/container_chips.dart index 1592ffe3..f3e481ef 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/container_chips.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/widgets/container_chips.dart @@ -35,7 +35,6 @@ import 'package:weblibre/features/geckoview/features/tabs/data/models/container_ import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart'; import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_chip_content.dart'; -import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_title.dart'; import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/tab_drag_container_target.dart'; import 'package:weblibre/features/geckoview/features/tabs/utils/container_colors.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; @@ -303,11 +302,13 @@ class ContainerChips extends HookConsumerWidget { WidgetsBinding.instance.addPostFrameCallback((_) { final activeContext = activeItemKey.value.currentContext; if (activeContext != null) { - Scrollable.ensureVisible( - activeContext, - alignment: 0.5, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, + unawaited( + Scrollable.ensureVisible( + activeContext, + alignment: 0.5, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + ), ); return; } @@ -336,11 +337,13 @@ class ContainerChips extends HookConsumerWidget { WidgetsBinding.instance.addPostFrameCallback((_) { final retryContext = activeItemKey.value.currentContext; if (retryContext != null) { - Scrollable.ensureVisible( - retryContext, - alignment: 0.5, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, + unawaited( + Scrollable.ensureVisible( + retryContext, + alignment: 0.5, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + ), ); } }); diff --git a/apps/weblibre/lib/features/onboarding/presentation/pages/welcome.dart b/apps/weblibre/lib/features/onboarding/presentation/pages/welcome.dart index 13fa9c61..41f85dc4 100644 --- a/apps/weblibre/lib/features/onboarding/presentation/pages/welcome.dart +++ b/apps/weblibre/lib/features/onboarding/presentation/pages/welcome.dart @@ -17,9 +17,9 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +import 'package:fading_scroll/fading_scroll.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:fading_scroll/fading_scroll.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:weblibre/core/design/app_colors.dart'; diff --git a/apps/weblibre/lib/features/proxy/domain/providers/proxy_connection_options.dart b/apps/weblibre/lib/features/proxy/domain/providers/proxy_connection_options.dart index 529979cc..7c9471fe 100644 --- a/apps/weblibre/lib/features/proxy/domain/providers/proxy_connection_options.dart +++ b/apps/weblibre/lib/features/proxy/domain/providers/proxy_connection_options.dart @@ -18,7 +18,6 @@ * along with this program. If not, see . */ import 'package:fast_equatable/fast_equatable.dart'; -import 'package:riverpod/riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:weblibre/core/logger.dart'; import 'package:weblibre/features/proxy/data/models/singbox_proxy_profile.dart'; diff --git a/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_profiles.dart b/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_profiles.dart index 44fdb25c..9add8375 100644 --- a/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_profiles.dart +++ b/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_profiles.dart @@ -18,7 +18,6 @@ * along with this program. If not, see . */ import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; -import 'package:riverpod/riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:weblibre/core/uuid.dart'; import 'package:weblibre/features/proxy/domain/repositories/singbox_proxy_credentials.dart'; diff --git a/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_runtime.dart b/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_runtime.dart index 618fa02f..7095c027 100644 --- a/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_runtime.dart +++ b/apps/weblibre/lib/features/proxy/domain/repositories/singbox_proxy_runtime.dart @@ -127,7 +127,7 @@ class SingboxProxyRuntimeRepository extends _$SingboxProxyRuntimeRepository { Future startProfile( String profileId, { SingboxProxyRuntimeOptions? options, - }) async { + }) { return _lock.synchronized(() async { final currentState = await _stateSnapshotUnlocked(); final activeProfileIds = _activeProfileIds(currentState); @@ -320,7 +320,7 @@ class SingboxProxyRuntimeRepository extends _$SingboxProxyRuntimeRepository { final profileMap = {for (final profile in profiles) profile.id: profile}; return Future.wait( - profileIds.map((profileId) async { + profileIds.map((profileId) { final profile = profileMap[profileId]; if (profile == null) { throw StateError('Unknown sing-box proxy profile: $profileId'); @@ -340,15 +340,15 @@ class SingboxProxyRuntimeRepository extends _$SingboxProxyRuntimeRepository { } @override - Future build() async { + Future build() { final plugin = ref.watch(singboxProxyClientProvider); final stateSubscription = plugin.stateStream.listen((nextState) { state = AsyncData(nextState); }); - ref.onDispose(() async { - await stateSubscription.cancel(); - await plugin.dispose(); + ref.onDispose(() { + unawaited(stateSubscription.cancel()); + unawaited(plugin.dispose()); }); return plugin.getState(); diff --git a/apps/weblibre/lib/features/proxy/domain/services/singbox_proxy_endpoint_sync.dart b/apps/weblibre/lib/features/proxy/domain/services/singbox_proxy_endpoint_sync.dart index da0ab24e..fa380bff 100644 --- a/apps/weblibre/lib/features/proxy/domain/services/singbox_proxy_endpoint_sync.dart +++ b/apps/weblibre/lib/features/proxy/domain/services/singbox_proxy_endpoint_sync.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_mozilla_components/flutter_mozilla_components.dart'; import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -104,13 +106,15 @@ class SingboxProxyEndpointSync extends _$SingboxProxyEndpointSync { (previous, next) { final runtimeState = next.value; if (runtimeState == null) return; - _sync(runtimeState).catchError((Object error, StackTrace stackTrace) { - logger.e( - 'Failed to sync sing-box proxy endpoints to Gecko', - error: error, - stackTrace: stackTrace, - ); - }); + unawaited( + _sync(runtimeState).catchError((Object error, StackTrace stackTrace) { + logger.e( + 'Failed to sync sing-box proxy endpoints to Gecko', + error: error, + stackTrace: stackTrace, + ); + }), + ); }, ); } diff --git a/apps/weblibre/lib/features/search_credits/data/search_backend_config.dart b/apps/weblibre/lib/features/search_credits/data/search_backend_config.dart index 65893bfe..2553fa80 100644 --- a/apps/weblibre/lib/features/search_credits/data/search_backend_config.dart +++ b/apps/weblibre/lib/features/search_credits/data/search_backend_config.dart @@ -17,25 +17,23 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -abstract final class SearchBackendConfig { - /// Clearnet origin used when the user has not opted to route search through - /// Tor. Must be a normal HTTPS URL (or HTTP for dev). - static const searchBackendOrigin = String.fromEnvironment( - 'SEARCH_BACKEND_ORIGIN', - defaultValue: 'https://search.weblibre.eu', - ); +/// Clearnet origin used when the user has not opted to route search through +/// Tor. Must be a normal HTTPS URL (or HTTP for dev). +const searchBackendOrigin = String.fromEnvironment( + 'SEARCH_BACKEND_ORIGIN', + defaultValue: 'https://search.weblibre.eu', +); - /// Origin used when the user opts to route search through Tor. Should be - /// the WebLibre search service's onion address so the Tor circuit - /// terminates inside the Tor network instead of exiting back to the - /// clearnet. Falls back to the clearnet origin when no onion address is - /// configured at build time. - static const searchBackendOriginTor = String.fromEnvironment( - 'SEARCH_BACKEND_ORIGIN_TOR', - defaultValue: - 'http://eyipgwt32zaejr2xwblaswp2ur4qikapofunbqus5dklvf7jxkncirad.onion', - ); +/// Origin used when the user opts to route search through Tor. Should be +/// the WebLibre search service's onion address so the Tor circuit +/// terminates inside the Tor network instead of exiting back to the +/// clearnet. Falls back to the clearnet origin when no onion address is +/// configured at build time. +const searchBackendOriginTor = String.fromEnvironment( + 'SEARCH_BACKEND_ORIGIN_TOR', + defaultValue: + 'http://eyipgwt32zaejr2xwblaswp2ur4qikapofunbqus5dklvf7jxkncirad.onion', +); - static Uri get originUri => Uri.parse(searchBackendOrigin); - static Uri get torOriginUri => Uri.parse(searchBackendOriginTor); -} +Uri get searchBackendOriginUri => Uri.parse(searchBackendOrigin); +Uri get searchBackendTorOriginUri => Uri.parse(searchBackendOriginTor); diff --git a/apps/weblibre/lib/features/search_credits/domain/providers.dart b/apps/weblibre/lib/features/search_credits/domain/providers.dart index ddd41152..65e4912d 100644 --- a/apps/weblibre/lib/features/search_credits/domain/providers.dart +++ b/apps/weblibre/lib/features/search_credits/domain/providers.dart @@ -33,9 +33,7 @@ BackendEndpoints searchBackendEndpoints(Ref ref) { webSearchSettingsControllerProvider.select((s) => s.routeThroughTor), ); return BackendEndpoints.fromOrigin( - routeThroughTor - ? SearchBackendConfig.torOriginUri - : SearchBackendConfig.originUri, + routeThroughTor ? searchBackendTorOriginUri : searchBackendOriginUri, ); } diff --git a/apps/weblibre/lib/features/settings/presentation/screens/contextual_toolbar_settings.dart b/apps/weblibre/lib/features/settings/presentation/screens/contextual_toolbar_settings.dart index c38996c0..ab55405c 100644 --- a/apps/weblibre/lib/features/settings/presentation/screens/contextual_toolbar_settings.dart +++ b/apps/weblibre/lib/features/settings/presentation/screens/contextual_toolbar_settings.dart @@ -99,8 +99,8 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget { pinned: true, delegate: _ToolbarPreviewDelegate(configs: configs.value), ), - SliverPadding( - padding: const EdgeInsets.fromLTRB(16, 20, 16, 0), + const SliverPadding( + padding: EdgeInsets.fromLTRB(16, 20, 16, 0), sliver: SliverToBoxAdapter(child: _SectionLabel(label: 'Enabled')), ), if (visibleConfigs.isEmpty) @@ -137,8 +137,8 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget { ); }, ), - SliverPadding( - padding: const EdgeInsets.fromLTRB(16, 20, 16, 0), + const SliverPadding( + padding: EdgeInsets.fromLTRB(16, 20, 16, 0), sliver: SliverToBoxAdapter(child: _SectionLabel(label: 'Disabled')), ), if (hiddenConfigs.isEmpty) diff --git a/apps/weblibre/lib/features/settings/presentation/screens/extensions_settings.dart b/apps/weblibre/lib/features/settings/presentation/screens/extensions_settings.dart index 04a9148c..ac009b67 100644 --- a/apps/weblibre/lib/features/settings/presentation/screens/extensions_settings.dart +++ b/apps/weblibre/lib/features/settings/presentation/screens/extensions_settings.dart @@ -25,7 +25,6 @@ import 'package:flutter_material_design_icons/flutter_material_design_icons.dart import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:weblibre/core/routing/routes.dart'; import 'package:weblibre/features/geckoview/features/browser/domain/services/browser_addon.dart'; -import 'package:weblibre/features/settings/presentation/widgets/custom_list_tile.dart'; import 'package:weblibre/features/settings/presentation/widgets/settings_detail.dart'; const List extensionsSettingsSections = [ diff --git a/apps/weblibre/lib/features/settings/presentation/screens/general_settings.dart b/apps/weblibre/lib/features/settings/presentation/screens/general_settings.dart index f2320c40..d3a1156f 100644 --- a/apps/weblibre/lib/features/settings/presentation/screens/general_settings.dart +++ b/apps/weblibre/lib/features/settings/presentation/screens/general_settings.dart @@ -17,7 +17,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import 'package:fading_scroll/fading_scroll.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart' diff --git a/apps/weblibre/lib/features/share_intent/domain/services/sharing_intent.dart b/apps/weblibre/lib/features/share_intent/domain/services/sharing_intent.dart index e641e5f0..9d5ca6c5 100644 --- a/apps/weblibre/lib/features/share_intent/domain/services/sharing_intent.dart +++ b/apps/weblibre/lib/features/share_intent/domain/services/sharing_intent.dart @@ -41,6 +41,7 @@ const _alwaysAllowPackageExtra = 'eu.weblibre.gatekeeper.always_allow_package'; StreamTransformer _buildSharingIntentTransformer( IntentGatekeeper gatekeeper, + GeneralSettingsRepository settingsRepository, ) => StreamTransformer.fromHandlers( handleData: (intent, sink) async { if (_extractAccountCallback(intent) != null) { @@ -53,14 +54,12 @@ _buildSharingIntentTransformer( final alwaysAllowPackage = intent.extra[_alwaysAllowPackageExtra] as String?; if (alwaysAllowPackage != null) { - await gatekeeper.ref - .read(generalSettingsRepositoryProvider.notifier) - .updateSettings( - (current) => current.copyWith.externalAppIntentPolicies({ - ...current.externalAppIntentPolicies, - alwaysAllowPackage: IntentSourcePolicy.allow, - }), - ); + await settingsRepository.updateSettings( + (current) => current.copyWith.externalAppIntentPolicies({ + ...current.externalAppIntentPolicies, + alwaysAllowPackage: IntentSourcePolicy.allow, + }), + ); } final shortcutContextId = intent.action == 'android.intent.action.VIEW' @@ -197,10 +196,13 @@ Raw> _consumeIntents( Raw> sharingIntentStream(Ref ref) { final receiver = ref.watch(intentReceiverProvider); final gatekeeper = ref.watch(intentGatekeeperProvider.notifier); + final settingsRepository = ref.watch( + generalSettingsRepositoryProvider.notifier, + ); return _consumeIntents( ref, receiver, - _buildSharingIntentTransformer(gatekeeper), + _buildSharingIntentTransformer(gatekeeper, settingsRepository), ); } diff --git a/apps/weblibre/lib/features/small_web/presentation/controllers/small_web_session_controller.dart b/apps/weblibre/lib/features/small_web/presentation/controllers/small_web_session_controller.dart index 2e7cb25d..48748be7 100644 --- a/apps/weblibre/lib/features/small_web/presentation/controllers/small_web_session_controller.dart +++ b/apps/weblibre/lib/features/small_web/presentation/controllers/small_web_session_controller.dart @@ -1,5 +1,3 @@ -// ignore_for_file: avoid_redundant_argument_values - /* * Copyright (c) 2024-2026 Fabian Freund. * diff --git a/apps/weblibre/lib/features/sync/domain/repositories/sync.dart b/apps/weblibre/lib/features/sync/domain/repositories/sync.dart index 7d8b3197..c1d8c4ff 100644 --- a/apps/weblibre/lib/features/sync/domain/repositories/sync.dart +++ b/apps/weblibre/lib/features/sync/domain/repositories/sync.dart @@ -315,21 +315,15 @@ class SyncRepository extends _$SyncRepository { _syncStartedSub = syncStateService.syncStartedEvents.listen((_) { _update( - (s) => s.copyWith( - lastSyncEvent: SyncEvent.started, - // ignore: avoid_redundant_argument_values - lastSyncError: null, - ), + (s) => + s.copyWith(lastSyncEvent: SyncEvent.started, lastSyncError: null), ); }); _syncCompletedSub = syncStateService.syncCompletedEvents.listen((_) { _update( - (s) => s.copyWith( - lastSyncEvent: SyncEvent.completed, - // ignore: avoid_redundant_argument_values - lastSyncError: null, - ), + (s) => + s.copyWith(lastSyncEvent: SyncEvent.completed, lastSyncError: null), ); unawaited(Future.wait([_refreshTabs(), _refreshDevices()])); }); diff --git a/apps/weblibre/lib/features/user/data/database/daos/cache.dart b/apps/weblibre/lib/features/user/data/database/daos/cache.dart index 278032e1..e40e25e2 100644 --- a/apps/weblibre/lib/features/user/data/database/daos/cache.dart +++ b/apps/weblibre/lib/features/user/data/database/daos/cache.dart @@ -19,10 +19,10 @@ */ import 'package:drift/drift.dart'; import 'package:weblibre/data/database/extensions/database_table_size.dart'; -import 'package:weblibre/features/user/data/icon_cache_marker.dart'; import 'package:weblibre/features/user/data/database/daos/cache.drift.dart'; import 'package:weblibre/features/user/data/database/database.dart'; import 'package:weblibre/features/user/data/database/definitions.drift.dart'; +import 'package:weblibre/features/user/data/icon_cache_marker.dart'; @DriftAccessor() class CacheDao extends DatabaseAccessor with $CacheDaoMixin { diff --git a/apps/weblibre/lib/features/user/data/database/daos/search_tokens.dart b/apps/weblibre/lib/features/user/data/database/daos/search_tokens.dart index 25674115..7bcc83d3 100644 --- a/apps/weblibre/lib/features/user/data/database/daos/search_tokens.dart +++ b/apps/weblibre/lib/features/user/data/database/daos/search_tokens.dart @@ -67,7 +67,7 @@ class SearchTokensDao extends DatabaseAccessor { /// Release any reservation older than [maxAge] — covers crashes mid-flight. /// Returns the number of rows released. - Future releaseStaleReservations(Duration maxAge) async { + Future releaseStaleReservations(Duration maxAge) { final cutoff = DateTime.now().subtract(maxAge); return (update(db.searchTokens)..where( (t) => diff --git a/apps/weblibre/lib/features/user/data/models/ublock_asset.dart b/apps/weblibre/lib/features/user/data/models/ublock_asset.dart index 5552e101..5a7be25b 100644 --- a/apps/weblibre/lib/features/user/data/models/ublock_asset.dart +++ b/apps/weblibre/lib/features/user/data/models/ublock_asset.dart @@ -261,7 +261,7 @@ class UBlockAssetsRegistry { return count; } - static UBlockAssetsRegistry fromJson(Map json) { + factory UBlockAssetsRegistry.fromJson(Map json) { final entries = {}; for (final entry in json.entries) { if (entry.value is Map) { diff --git a/apps/weblibre/lib/features/web_search/data/locale_options.dart b/apps/weblibre/lib/features/web_search/data/locale_options.dart index 782418ef..e39f95e7 100644 --- a/apps/weblibre/lib/features/web_search/data/locale_options.dart +++ b/apps/weblibre/lib/features/web_search/data/locale_options.dart @@ -17,16 +17,15 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -library; -/// Curated picker options for the web-search language and country selectors. -/// -/// Codes intersect what Brave (`search_lang`/`country`) and Mojeek -/// (`lb`/`rb`) accept; English display names so the menu doesn't need a -/// per-locale translation pass. The protocol carries just the primary -/// ISO 639-1 / ISO 3166-1 alpha-2 codes — region qualifiers (`en-gb`, -/// `pt-br`, etc.) are reconstructed server-side from the language+country -/// pair. +// Curated picker options for the web-search language and country selectors. +// +// Codes intersect what Brave (`search_lang`/`country`) and Mojeek +// (`lb`/`rb`) accept; English display names so the menu doesn't need a +// per-locale translation pass. The protocol carries just the primary +// ISO 639-1 / ISO 3166-1 alpha-2 codes — region qualifiers (`en-gb`, +// `pt-br`, etc.) are reconstructed server-side from the language+country +// pair. class LanguageOption { final String code; // ISO 639-1 diff --git a/apps/weblibre/lib/features/web_search/domain/controllers/sandbox_capture_controller.dart b/apps/weblibre/lib/features/web_search/domain/controllers/sandbox_capture_controller.dart index 9fc23607..15d4e982 100644 --- a/apps/weblibre/lib/features/web_search/domain/controllers/sandbox_capture_controller.dart +++ b/apps/weblibre/lib/features/web_search/domain/controllers/sandbox_capture_controller.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart' as fmc; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:search_protocol/search_protocol.dart'; import 'package:search_client/search_client.dart'; import 'package:weblibre/core/routing/routes.dart'; import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart'; @@ -18,9 +17,9 @@ import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode import 'package:weblibre/features/geckoview/features/tabs/data/providers.dart'; import 'package:weblibre/features/search_credits/domain/controllers/search_token_issuance_controller.dart'; import 'package:weblibre/features/search_credits/domain/providers.dart'; +import 'package:weblibre/features/search_credits/domain/providers/proxy_client.dart'; import 'package:weblibre/features/search_credits/domain/repositories/search_token_stash_repository.dart'; import 'package:weblibre/features/user/domain/repositories/cache.dart'; -import 'package:weblibre/features/search_credits/domain/providers/proxy_client.dart'; import 'package:weblibre/features/web_search/domain/services/capture_artifact_downloader.dart'; import 'package:weblibre/features/web_search/domain/services/capture_server.dart'; import 'package:weblibre/features/web_search/domain/services/sandbox_capture_store.dart'; @@ -114,7 +113,7 @@ SandboxCaptureStore sandboxCaptureStore(Ref ref) => SandboxCaptureStore(); @Riverpod(keepAlive: true) Stream sandboxCaptureErrors(Ref ref) { final ctrl = ref.watch(sandboxCaptureControllerProvider.notifier); - return ctrl.errors; + return ctrl.errorStream(); } /// Orchestrates sandbox capture browsing: @@ -148,10 +147,7 @@ class SandboxCaptureController extends _$SandboxCaptureController { static const _defaultMethod = 'singlefile'; static const _defaultVariant = 'balanced'; - StreamSubscription>? _captureTabSub; - StreamSubscription? _retrySub; - - Stream get errors => _errors.stream; + Stream errorStream() => _errors.stream; @override void build() { @@ -159,9 +155,9 @@ class SandboxCaptureController extends _$SandboxCaptureController { fmc.SandboxCaptureHostEvents.setUp(_hostEvents); final dao = ref.read(tabDatabaseProvider).captureTabDao; - _captureTabSub = dao.watchAll().listen(_onCaptureTabChange); + final captureTabSub = dao.watchAll().listen(_onCaptureTabChange); - _retrySub = ref + final retrySub = ref .read(captureServerProvider) .retryRequests .listen(_onRetryRequest); @@ -173,10 +169,8 @@ class SandboxCaptureController extends _$SandboxCaptureController { // stream — otherwise an in-flight Pigeon event or DAO emit could // race with handler cleanup, or _markFailed could try to add to a // closed _errors sink. - final captureTabSub = _captureTabSub; - final retrySub = _retrySub; - if (captureTabSub != null) unawaited(captureTabSub.cancel()); - if (retrySub != null) unawaited(retrySub.cancel()); + unawaited(captureTabSub.cancel()); + unawaited(retrySub.cancel()); fmc.SandboxCaptureHostEvents.setUp(null); _hostEvents.controller = null; unawaited(_errors.close()); diff --git a/apps/weblibre/lib/features/web_search/domain/controllers/search_controller.dart b/apps/weblibre/lib/features/web_search/domain/controllers/search_controller.dart index 657bea3f..b97c065c 100644 --- a/apps/weblibre/lib/features/web_search/domain/controllers/search_controller.dart +++ b/apps/weblibre/lib/features/web_search/domain/controllers/search_controller.dart @@ -4,7 +4,6 @@ import 'dart:typed_data'; import 'package:riverpod/riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:search_protocol/search_protocol.dart'; import 'package:search_client/search_client.dart'; import 'package:weblibre/domain/services/generic_website.dart'; import 'package:weblibre/features/search_credits/domain/controllers/search_token_issuance_controller.dart'; @@ -1226,7 +1225,10 @@ class WebSearchScrollOffset extends _$WebSearchScrollOffset { @override double build() => 0; - void update(double offset) => state = offset; + void update(double offset) { + if (state == offset) return; + state = offset; + } void reset() => state = 0; } diff --git a/apps/weblibre/lib/features/web_search/domain/services/capture_artifact_downloader.dart b/apps/weblibre/lib/features/web_search/domain/services/capture_artifact_downloader.dart index 8571801d..b4a27bd1 100644 --- a/apps/weblibre/lib/features/web_search/domain/services/capture_artifact_downloader.dart +++ b/apps/weblibre/lib/features/web_search/domain/services/capture_artifact_downloader.dart @@ -5,7 +5,6 @@ import 'dart:ui'; import 'package:http/http.dart' as http; import 'package:path/path.dart' as p; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:search_protocol/search_protocol.dart'; import 'package:search_client/search_client.dart'; import 'package:weblibre/core/filesystem.dart'; import 'package:weblibre/features/search_credits/domain/providers.dart'; diff --git a/apps/weblibre/lib/features/web_search/domain/services/capture_server.dart b/apps/weblibre/lib/features/web_search/domain/services/capture_server.dart index a4033840..f83e4f7f 100644 --- a/apps/weblibre/lib/features/web_search/domain/services/capture_server.dart +++ b/apps/weblibre/lib/features/web_search/domain/services/capture_server.dart @@ -361,14 +361,14 @@ class CaptureServer { final tabIdJson = jsonEncode(tabId); final captureIdJson = jsonEncode(captureId); final html = - '' - '' - 'Capturing…' - '$body' - '' - '' - ''; + ''' + + +Capturing… +$body + + +'''; request.response.write(html); await request.response.close(); } @@ -510,35 +510,24 @@ class CaptureServer { "base-uri 'none'; " "form-action 'self'"; - static const _loaderStyles = - 'html,body{height:100%}' - 'body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,' - 'sans-serif;display:flex;align-items:center;justify-content:center;' - 'min-height:100vh;margin:0;background:#0b0d10;color:#e6e8eb}' - 'main{text-align:center;max-width:480px;padding:32px;opacity:0;' - 'animation:fade .35s ease-out forwards}' - '@keyframes fade{to{opacity:1}}' - '.spinner{width:56px;height:56px;margin:0 auto 20px;border-radius:50%;' - 'border:3px solid rgba(255,255,255,.08);border-top-color:#7aa2f7;' - 'animation:spin 1s linear infinite}' - '@keyframes spin{to{transform:rotate(360deg)}}' - 'h1{font-size:18px;font-weight:600;margin:0 0 8px;letter-spacing:.2px}' - 'p{margin:0;color:#9aa1a8;font-size:14px;line-height:1.5}' - '.dots::after{display:inline-block;width:1.2em;text-align:left;' - 'animation:dots 1.4s steps(4,end) infinite;content:""}' - '@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}' - '75%{content:"..."}100%{content:""}}' - '.error h1{color:#f7768e}' - '.actions{margin-top:20px;display:flex;gap:8px;justify-content:center}' - '.btn{padding:10px 16px;border:0;border-radius:10px;cursor:pointer;' - 'font:inherit;font-weight:600;background:#7aa2f7;color:#0b0d10}' - '.btn.secondary{background:transparent;color:#9aa1a8;' - 'border:1px solid rgba(255,255,255,.12)}' - '.hidden{display:none}' - '@media(prefers-color-scheme:light){body{background:#f5f6f8;' - 'color:#1a1d22}.spinner{border-color:rgba(0,0,0,.08);' - 'border-top-color:#3b82f6}.btn{background:#3b82f6;color:white}' - 'p{color:#52606b}}'; + static const _loaderStyles = ''' +html,body{height:100%} +body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0b0d10;color:#e6e8eb} +main{text-align:center;max-width:480px;padding:32px;opacity:0;animation:fade .35s ease-out forwards} +@keyframes fade{to{opacity:1}} +.spinner{width:56px;height:56px;margin:0 auto 20px;border-radius:50%;border:3px solid rgba(255,255,255,.08);border-top-color:#7aa2f7;animation:spin 1s linear infinite} +@keyframes spin{to{transform:rotate(360deg)}} +h1{font-size:18px;font-weight:600;margin:0 0 8px;letter-spacing:.2px} +p{margin:0;color:#9aa1a8;font-size:14px;line-height:1.5} +.dots::after{display:inline-block;width:1.2em;text-align:left;animation:dots 1.4s steps(4,end) infinite;content:""} +@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}100%{content:""}} +.error h1{color:#f7768e} +.actions{margin-top:20px;display:flex;gap:8px;justify-content:center} +.btn{padding:10px 16px;border:0;border-radius:10px;cursor:pointer;font:inherit;font-weight:600;background:#7aa2f7;color:#0b0d10} +.btn.secondary{background:transparent;color:#9aa1a8;border:1px solid rgba(255,255,255,.12)} +.hidden{display:none} +@media(prefers-color-scheme:light){body{background:#f5f6f8;color:#1a1d22}.spinner{border-color:rgba(0,0,0,.08);border-top-color:#3b82f6}.btn{background:#3b82f6;color:white}p{color:#52606b}} +'''; // Inline script for the loader shell. Reads window.__TAB_ID__ and // window.__CAPTURE_ID__, long-polls /loader/wait, then either redirects @@ -548,7 +537,7 @@ class CaptureServer { // service has gone away doesn't busy-loop forever — after the cap the // loader gives up and shows the error pane with a Retry button (which // resets the counter via showPending → poll()). - static const _loaderScript = r''' + static const _loaderScript = ''' (function(){ var pending=document.getElementById('pending'); var error=document.getElementById('error'); @@ -606,18 +595,19 @@ class CaptureServer { String _loaderShellBody({required bool initialError}) { final pendingClass = initialError ? 'hidden' : ''; final errorClass = initialError ? 'error' : 'error hidden'; - return '
' - '
' - '

Capturing page

' - '

Saving an offline copy. This usually takes a few seconds.

' - '
' - '
' - '

Capture failed

' - '

The page could not be saved. Check the notification for details.

' - '
' - '' - '
' - '
'; + return ''' +
+
+

Capturing page

+

Saving an offline copy. This usually takes a few seconds.

+
+
+

Capture failed

+

The page could not be saved. Check the notification for details.

+
+ +
+
'''; } } diff --git a/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_card.dart b/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_card.dart index ac71ec5d..8a2ce9b2 100644 --- a/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_card.dart +++ b/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_card.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; -import 'package:fast_equatable/fast_equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -211,7 +210,7 @@ class _ContentRow extends StatelessWidget { /// instances on every state mutation). Equality is driven instead by scalar /// signatures derived from those collections, which is enough to detect any /// change a single result card cares about. -class _FooterState with FastEquatable { +class _FooterState { final bool hasOpenSession; final bool isFetching; final bool isFetched; @@ -260,14 +259,26 @@ class _FooterState with FastEquatable { } @override - List get hashParameters => [ + bool operator ==(Object other) { + return identical(this, other) || + other is _FooterState && + hasOpenSession == other.hasOpenSession && + isFetching == other.isFetching && + isFetched == other.isFetched && + fetchError == other.fetchError && + _capturingSignature == other._capturingSignature && + _capturesSignature == other._capturesSignature; + } + + @override + int get hashCode => Object.hash( hasOpenSession, isFetching, isFetched, fetchError, _capturingSignature, _capturesSignature, - ]; + ); } class _FetchFooter extends ConsumerWidget { diff --git a/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_metadata_chips.dart b/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_metadata_chips.dart index c524392c..cb7a7787 100644 --- a/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_metadata_chips.dart +++ b/apps/weblibre/lib/features/web_search/presentation/widgets/search_result_metadata_chips.dart @@ -151,10 +151,10 @@ bool _languageMatchesQuery(String resultLanguage, String? queryTag) { final result = resultLanguage .trim() .toLowerCase() - .split(RegExp(r'[-_]')) + .split(RegExp('[-_]')) .first; - final query = queryTag.trim().toLowerCase().split(RegExp(r'[-_]')).first; + final query = queryTag.trim().toLowerCase().split(RegExp('[-_]')).first; if (result.isEmpty || query.isEmpty) return false; diff --git a/apps/weblibre/pubspec.yaml b/apps/weblibre/pubspec.yaml index 51e278d6..5c587cd3 100644 --- a/apps/weblibre/pubspec.yaml +++ b/apps/weblibre/pubspec.yaml @@ -16,7 +16,6 @@ dependencies: country_codes: ^3.3.0 country_flags: ^4.1.2 crypto: ^3.0.7 - xxh3: ^1.2.0 cryptography_flutter: ^2.3.4 device_info_plus: ^12.4.0 drift: ^2.31.0 @@ -31,15 +30,15 @@ dependencies: sdk: flutter flutter_auto_size_text: ^5.0.0 flutter_hooks: ^0.21.3+1 - flutter_secure_storage: ^10.1.0 flutter_markdown: ^0.7.7+1 flutter_material_design_icons: ^3.1.0+7447 flutter_mozilla_components: path: ../../packages/flutter_mozilla_components flutter_reorderable_grid_view: ^5.6.0 - flutter_slidable: ^4.0.3 + flutter_secure_storage: ^10.1.0 flutter_singbox_proxy: path: ../../packages/flutter_singbox_proxy + flutter_slidable: ^4.0.3 flutter_svg: ^2.3.0 flutter_tor: path: ../../packages/flutter_tor @@ -67,13 +66,9 @@ dependencies: path: ^1.9.1 path_provider: ^2.1.5 permission_handler: ^12.0.1 + pretty_qr_code: ^3.6.0 privacypass_client: path: ../../../weblibre_account/packages/privacypass_client - search_client: - path: ../../../weblibre_account/packages/search_client - search_protocol: - path: ../../../weblibre_account/packages/search_protocol - pretty_qr_code: ^3.6.0 qr_code_scanner_plus: ^2.1.1 quick_actions: ^1.1.0 riverpod: ^3.2.1 @@ -82,6 +77,10 @@ dependencies: rxdart: ^0.28.0 saf_stream: ^2.0.0 saf_util: ^2.1.0 + search_client: + path: ../../../weblibre_account/packages/search_client + search_protocol: + path: ../../../weblibre_account/packages/search_protocol secure_archive: git: url: https://github.com/FaFre/secure_archive.git @@ -97,8 +96,8 @@ dependencies: speech_to_text_dialog: path: ../../packages/speech_to_text_dialog sqlite3: ^2.9.4 - supabase: ^2.10.6 sqlite3_flutter_libs: "0.5.41" + supabase: ^2.10.6 synchronized: ^3.4.0+1 text_scroll: ^0.2.1 timeago: ^3.7.1 @@ -106,8 +105,9 @@ dependencies: git: url: https://github.com/FaFre/uri-to-file.git url_launcher: ^6.3.2 - web_socket_channel: ^3.0.3 uuid: ^4.5.3 + web_socket_channel: ^3.0.3 + xxh3: ^1.2.0 dev_dependencies: build_runner: ^2.15.0 diff --git a/apps/weblibre/test/domain/services/generic_website_test.dart b/apps/weblibre/test/domain/services/generic_website_test.dart index 88a3e94a..959a3de8 100644 --- a/apps/weblibre/test/domain/services/generic_website_test.dart +++ b/apps/weblibre/test/domain/services/generic_website_test.dart @@ -1,12 +1,11 @@ -import 'dart:typed_data'; import 'dart:ui'; import 'package:drift/drift.dart' show Variable; import 'package:drift/native.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:riverpod/riverpod.dart'; import 'package:weblibre/data/database/functions/lexo_rank_functions.dart'; import 'package:weblibre/domain/services/favicon_resolver.dart'; @@ -222,23 +221,26 @@ final _generatorResult = IconResult( ); final _cachedSvgBytes = Uint8List.fromList( - '' - '' - '' + ''' + + +''' .codeUnits, ); final _updatedSvgBytes = Uint8List.fromList( - '' - '' - '' + ''' + + +''' .codeUnits, ); final _generatedSvgBytes = Uint8List.fromList( - '' - '' - 'W' - '' + ''' + + +W +''' .codeUnits, ); diff --git a/apps/weblibre/test/features/account/presentation/widgets/subscription_card_test.dart b/apps/weblibre/test/features/account/presentation/widgets/subscription_card_test.dart index e5572c5e..77390d48 100644 --- a/apps/weblibre/test/features/account/presentation/widgets/subscription_card_test.dart +++ b/apps/weblibre/test/features/account/presentation/widgets/subscription_card_test.dart @@ -83,19 +83,21 @@ void main() { tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed); await tester.pump(); - expect(repository.refreshCount, 1); + expect(repository.refreshCount(), 1); }, ); } class _FakeSubscriptionRepository extends SubscriptionRepository { - int refreshCount = 0; + int _refreshCount = 0; + + int refreshCount() => _refreshCount; @override Future build() async => SubscriptionStatus.inactive; @override Future refresh() async { - refreshCount++; + _refreshCount++; } } diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart index 1286b099..9a574a47 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart @@ -18,8 +18,6 @@ * along with this program. If not, see . */ -// ignore_for_file: avoid_redundant_argument_values - import 'dart:io'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart index 6112b7dc..914afa5b 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart @@ -12,7 +12,6 @@ import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references // ignore_for_file: deprecated_member_use diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart index baa79b10..afabc7dd 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -// ignore_for_file: avoid_redundant_argument_values, avoid_dynamic_calls +// ignore_for_file: avoid_dynamic_calls import 'dart:convert'; import 'dart:io'; diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart index b5a7657a..7e546fba 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart @@ -12,7 +12,6 @@ import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references // ignore_for_file: deprecated_member_use diff --git a/apps/weblibre/test/features/geckoview/features/browser/domain/services/proxy_settings_replication_test.dart b/apps/weblibre/test/features/geckoview/features/browser/domain/services/proxy_settings_replication_test.dart index 6a428060..365e6718 100644 --- a/apps/weblibre/test/features/geckoview/features/browser/domain/services/proxy_settings_replication_test.dart +++ b/apps/weblibre/test/features/geckoview/features/browser/domain/services/proxy_settings_replication_test.dart @@ -28,7 +28,7 @@ void main() { test( 'container assignments ensure sing-box profiles are running before syncing', () async { - final profileId = SingboxProxyConnectionId('profile-1'); + const profileId = SingboxProxyConnectionId('profile-1'); final assignedContainer = _container( id: 'container-1', contextId: 'context-a', diff --git a/apps/weblibre/test/features/geckoview/features/open_link_tools/domain/services/url_cleaner_service_test.dart b/apps/weblibre/test/features/geckoview/features/open_link_tools/domain/services/url_cleaner_service_test.dart index 54ddf26b..dd4766dc 100644 --- a/apps/weblibre/test/features/geckoview/features/open_link_tools/domain/services/url_cleaner_service_test.dart +++ b/apps/weblibre/test/features/geckoview/features/open_link_tools/domain/services/url_cleaner_service_test.dart @@ -439,7 +439,6 @@ void main() { UrlCleanerRule( name: 'test', data: UrlCleanerRuleData( - // ignore: avoid_redundant_argument_values completeProvider: false, urlPattern: r'^https?://example\.com', rules: ['track'], diff --git a/apps/weblibre/test/features/geckoview/features/tabs/presentation/screens/container_edit_test.dart b/apps/weblibre/test/features/geckoview/features/tabs/presentation/screens/container_edit_test.dart index ccabd60f..388adb93 100644 --- a/apps/weblibre/test/features/geckoview/features/tabs/presentation/screens/container_edit_test.dart +++ b/apps/weblibre/test/features/geckoview/features/tabs/presentation/screens/container_edit_test.dart @@ -24,7 +24,7 @@ void main() { color: Colors.blue, orderKey: 'a', metadata: ContainerMetadata.withDefaults( - proxyConnectionId: SingboxProxyConnectionId('missing-proxy'), + proxyConnectionId: const SingboxProxyConnectionId('missing-proxy'), ), ), ), diff --git a/apps/weblibre/test/features/proxy/domain/repositories/singbox_proxy_runtime_test.dart b/apps/weblibre/test/features/proxy/domain/repositories/singbox_proxy_runtime_test.dart index ea0bc9c7..e8075bc1 100644 --- a/apps/weblibre/test/features/proxy/domain/repositories/singbox_proxy_runtime_test.dart +++ b/apps/weblibre/test/features/proxy/domain/repositories/singbox_proxy_runtime_test.dart @@ -438,7 +438,7 @@ class _FakeContainerRepository extends ContainerRepository { class _FakeProxyRoutingSettingsRepository extends ProxyRoutingSettingsRepository { - ProxyRoutingSettings? _settings; + final ProxyRoutingSettings? _settings; _FakeProxyRoutingSettingsRepository([this._settings]); diff --git a/apps/weblibre/test/features/user/data/models/ublock_filter_list_settings_test.dart b/apps/weblibre/test/features/user/data/models/ublock_filter_list_settings_test.dart index 11d1cd29..8b8a77cc 100644 --- a/apps/weblibre/test/features/user/data/models/ublock_filter_list_settings_test.dart +++ b/apps/weblibre/test/features/user/data/models/ublock_filter_list_settings_test.dart @@ -127,16 +127,18 @@ void main() { test('buildGroupedParentTree creates correct hierarchy', () { final registry = _makeRegistry(); final tree = registry.buildGroupedParentTree(); + final defaultGroup = tree[UBlockAssetGroup.$default]; + final adsGroup = tree[UBlockAssetGroup.ads]; expect(tree, contains(UBlockAssetGroup.$default)); - expect(tree[UBlockAssetGroup.$default]!, contains('uBlock filters')); + expect(defaultGroup, contains('uBlock filters')); expect( - tree[UBlockAssetGroup.$default]!['uBlock filters'], + defaultGroup?['uBlock filters'], containsAll(['ublock-filters', 'ublock-privacy']), ); expect(tree, contains(UBlockAssetGroup.ads)); - expect(tree[UBlockAssetGroup.ads]!, contains(null)); - expect(tree[UBlockAssetGroup.ads]![null], contains('easylist')); + expect(adsGroup, contains(null)); + expect(adsGroup?[null], contains('easylist')); expect(tree, contains(UBlockAssetGroup.regions)); }); diff --git a/apps/weblibre/test/presentation/main_app_test.dart b/apps/weblibre/test/presentation/main_app_test.dart index 7dd4c01c..f79aaeaa 100644 --- a/apps/weblibre/test/presentation/main_app_test.dart +++ b/apps/weblibre/test/presentation/main_app_test.dart @@ -34,7 +34,6 @@ void main() { ); test('forces animations off when the app setting is enabled', () { - // ignore: avoid_redundant_argument_values const mediaQuery = MediaQueryData(disableAnimations: false); final result = applyAppMediaQueryOverrides( diff --git a/apps/weblibre/test/presentation/widgets/url_icon_test.dart b/apps/weblibre/test/presentation/widgets/url_icon_test.dart index 4a33cf32..23c4d38c 100644 --- a/apps/weblibre/test/presentation/widgets/url_icon_test.dart +++ b/apps/weblibre/test/presentation/widgets/url_icon_test.dart @@ -3,9 +3,9 @@ import 'dart:typed_data'; import 'package:drift/native.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:weblibre/data/database/functions/lexo_rank_functions.dart'; import 'package:weblibre/domain/services/favicon_resolver.dart'; @@ -128,7 +128,7 @@ void main() { final class _NeverCalledResolver implements FaviconResolver { @override - Future resolve(Uri url, {int? proxyPort}) async { + Future resolve(Uri url, {int? proxyPort}) { throw UnimplementedError('cacheOnly should not hit the resolver'); } } diff --git a/packages/flutter_mozilla_components/example/lib/main.dart b/packages/flutter_mozilla_components/example/lib/main.dart index 00bdf82b..4f0a53e3 100644 --- a/packages/flutter_mozilla_components/example/lib/main.dart +++ b/packages/flutter_mozilla_components/example/lib/main.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; void main() { - runApp(const MyApp()); + runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatefulWidget { diff --git a/packages/flutter_mozilla_components/example/pubspec.yaml b/packages/flutter_mozilla_components/example/pubspec.yaml index c3699c36..3565f9fc 100644 --- a/packages/flutter_mozilla_components/example/pubspec.yaml +++ b/packages/flutter_mozilla_components/example/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: flutter_mozilla_components: path: ../ + hooks_riverpod: ^3.3.1 dev_dependencies: flutter_test: diff --git a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart index 41b3caf1..fee6bcdf 100644 --- a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart +++ b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart @@ -69,8 +69,8 @@ export 'src/pigeons/gecko.g.dart' GeckoDeleteBrowsingDataController, GeckoEngineSettings, GeckoFetchResponse, - GeckoProxySettings, GeckoPref, + GeckoProxySettings, GeckoPublicSuffixListApi, GeckoPwaApi, GeckoSitePermissionsApi, diff --git a/packages/flutter_singbox_proxy/example/integration_test/plugin_integration_test.dart b/packages/flutter_singbox_proxy/example/integration_test/plugin_integration_test.dart index 35390277..7fbd021d 100644 --- a/packages/flutter_singbox_proxy/example/integration_test/plugin_integration_test.dart +++ b/packages/flutter_singbox_proxy/example/integration_test/plugin_integration_test.dart @@ -6,11 +6,10 @@ // For more information about Flutter integration tests, please see // https://flutter.dev/to/integration-testing +import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); diff --git a/packages/flutter_singbox_proxy/example/lib/main.dart b/packages/flutter_singbox_proxy/example/lib/main.dart index 149c6879..34d6fff5 100644 --- a/packages/flutter_singbox_proxy/example/lib/main.dart +++ b/packages/flutter_singbox_proxy/example/lib/main.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; void main() { - runApp(const MyApp()); + runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { diff --git a/packages/flutter_singbox_proxy/example/pubspec.yaml b/packages/flutter_singbox_proxy/example/pubspec.yaml index 136890e0..a5896ddd 100644 --- a/packages/flutter_singbox_proxy/example/pubspec.yaml +++ b/packages/flutter_singbox_proxy/example/pubspec.yaml @@ -15,6 +15,7 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: + cupertino_icons: ^1.0.8 flutter: sdk: flutter @@ -25,24 +26,20 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 + hooks_riverpod: ^3.3.1 dev_dependencies: - integration_test: - sdk: flutter + flutter_lints: ^6.0.0 flutter_test: sdk: flutter + integration_test: + sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^6.0.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/packages/flutter_singbox_proxy/example/test/widget_test.dart b/packages/flutter_singbox_proxy/example/test/widget_test.dart index ee8663d8..a3d226be 100644 --- a/packages/flutter_singbox_proxy/example/test/widget_test.dart +++ b/packages/flutter_singbox_proxy/example/test/widget_test.dart @@ -6,9 +6,8 @@ // tree, read text, and verify that the values of widget properties are correct. import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - import 'package:flutter_singbox_proxy_example/main.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('shows proxy runtime status label', (WidgetTester tester) async { diff --git a/packages/flutter_singbox_proxy/lib/flutter_singbox_proxy.dart b/packages/flutter_singbox_proxy/lib/flutter_singbox_proxy.dart index d57a1cfc..1c99e9ef 100644 --- a/packages/flutter_singbox_proxy/lib/flutter_singbox_proxy.dart +++ b/packages/flutter_singbox_proxy/lib/flutter_singbox_proxy.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'src/singbox_proxy_api.g.dart'; +import 'package:flutter_singbox_proxy/src/singbox_proxy_api.g.dart'; export 'src/singbox_proxy_api.g.dart' show diff --git a/packages/flutter_singbox_proxy/test/flutter_singbox_proxy_test.dart b/packages/flutter_singbox_proxy/test/flutter_singbox_proxy_test.dart index 06aba1bf..25150748 100644 --- a/packages/flutter_singbox_proxy/test/flutter_singbox_proxy_test.dart +++ b/packages/flutter_singbox_proxy/test/flutter_singbox_proxy_test.dart @@ -1,5 +1,5 @@ -import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { test('profile model keeps generic sing-box config boundary', () { diff --git a/packages/flutter_tor/example/lib/main.dart b/packages/flutter_tor/example/lib/main.dart index cfdfa4b9..2f125739 100644 --- a/packages/flutter_tor/example/lib/main.dart +++ b/packages/flutter_tor/example/lib/main.dart @@ -6,10 +6,11 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_tor/flutter_tor.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:socks5_proxy/socks_client.dart'; void main() { - runApp(const MyApp()); + runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { diff --git a/packages/flutter_tor/example/pubspec.yaml b/packages/flutter_tor/example/pubspec.yaml index 2375a179..54110d20 100644 --- a/packages/flutter_tor/example/pubspec.yaml +++ b/packages/flutter_tor/example/pubspec.yaml @@ -19,6 +19,7 @@ dependencies: sdk: flutter flutter_tor: path: ../ + hooks_riverpod: ^3.3.1 # HTTP client for testing Tor connectivity http: ^1.6.0 diff --git a/packages/simple_intent_receiver/example/lib/main.dart b/packages/simple_intent_receiver/example/lib/main.dart index 99e81cf2..96c9b6d2 100644 --- a/packages/simple_intent_receiver/example/lib/main.dart +++ b/packages/simple_intent_receiver/example/lib/main.dart @@ -18,6 +18,7 @@ * along with this program. If not, see . */ import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:logger/logger.dart'; import 'package:simple_intent_receiver/simple_intent_receiver.dart'; @@ -34,7 +35,7 @@ void main() { logger.d(data.action); }); - runApp(const MyApp()); + runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { diff --git a/packages/simple_intent_receiver/example/pubspec.yaml b/packages/simple_intent_receiver/example/pubspec.yaml index 1c2987e4..940eefc8 100644 --- a/packages/simple_intent_receiver/example/pubspec.yaml +++ b/packages/simple_intent_receiver/example/pubspec.yaml @@ -17,6 +17,7 @@ environment: dependencies: flutter: sdk: flutter + hooks_riverpod: ^3.3.1 logger: ^2.7.0 simple_intent_receiver: # When depending on this package from a real application you should use: diff --git a/packages/speech_to_text_dialog/example/lib/main.dart b/packages/speech_to_text_dialog/example/lib/main.dart index 6aa4fb13..d3cc7975 100644 --- a/packages/speech_to_text_dialog/example/lib/main.dart +++ b/packages/speech_to_text_dialog/example/lib/main.dart @@ -1,10 +1,11 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:speech_to_text_dialog/speech_to_text_dialog.dart'; void main() { - runApp(const MyApp()); + runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatefulWidget { diff --git a/packages/speech_to_text_dialog/example/pubspec.yaml b/packages/speech_to_text_dialog/example/pubspec.yaml index a601bc98..878fdc04 100644 --- a/packages/speech_to_text_dialog/example/pubspec.yaml +++ b/packages/speech_to_text_dialog/example/pubspec.yaml @@ -17,6 +17,7 @@ environment: dependencies: flutter: sdk: flutter + hooks_riverpod: ^3.3.1 speech_to_text_dialog: # When depending on this package from a real application you should use: