Add proxy routing and sing-box support

This commit is contained in:
Fabian Freund
2026-05-22 18:16:31 +02:00
parent 51289f1266
commit a5974617aa
262 changed files with 32003 additions and 3962 deletions
@@ -125,7 +125,9 @@ class _MethodTile extends ConsumerWidget {
failed: failed,
colorScheme: colorScheme,
),
onTap: busy ? null : () => _handleTap(context, ref, ready, failed, captured),
onTap: busy
? null
: () => _handleTap(context, ref, ready, failed, captured),
);
}
@@ -200,9 +202,6 @@ class _StatusIndicator extends StatelessWidget {
if (failed) {
return Icon(Icons.refresh, color: colorScheme.error);
}
return Icon(
Icons.download_rounded,
color: colorScheme.onSurfaceVariant,
);
return Icon(Icons.download_rounded, color: colorScheme.onSurfaceVariant);
}
}
@@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:intl/intl.dart';
import 'package:nullability/nullability.dart';
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
class PageMetadataChips extends HookWidget {
final PageMetadata metadata;
@@ -22,6 +22,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/core/design/app_colors.dart';
import 'package:weblibre/features/search_credits/domain/providers/proxy_client.dart';
import 'package:weblibre/features/search_credits/domain/repositories/web_search_settings.dart';
import 'package:weblibre/features/tor/domain/extensions/tor_status_x.dart';
import 'package:weblibre/features/tor/domain/services/tor_proxy.dart';
import 'package:weblibre/features/tor/presentation/controllers/start_tor_proxy.dart';
import 'package:weblibre/presentation/hooks/on_initialization.dart';
@@ -55,10 +56,9 @@ class RouteThroughTorToggle extends HookConsumerWidget {
final torStatus = ref.watch(torProxyServiceProvider).value;
final activePort = ref.watch(searchProxyPortProvider);
final bootstrapProgress = torStatus?.bootstrapProgress ?? 0;
final showSpinner =
routeThroughTor && (activePort == null || bootstrapProgress < 100);
routeThroughTor &&
(activePort == null || !(torStatus?.isReady ?? false));
// Push the latest native status into the stream on first build so the
// bar reflects real progress even when the user lands on the search
@@ -161,14 +161,13 @@ class WebSearchTorBootstrapProgress extends HookConsumerWidget {
final torAsync = ref.watch(torProxyServiceProvider);
final status = torAsync.value;
final isRunning = status?.isRunning ?? false;
final bootstrapProgress = status?.bootstrapProgress ?? 0;
// Hide once Tor is fully running and bootstrapped — otherwise, mirror
// the Tor settings screen and always show a determinate bar (value
// anchored to the live bootstrap progress, never indeterminate, so the
// user can actually track the percentage).
if (isRunning && bootstrapProgress >= 100) return const SizedBox.shrink();
if (status?.isReady ?? false) return const SizedBox.shrink();
final appColors = AppColors.of(context);
return Padding(
@@ -19,7 +19,7 @@
*/
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
import 'package:weblibre/features/search_credits/domain/repositories/web_search_settings.dart';
import 'package:weblibre/features/web_search/data/locale_options.dart';
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
import 'package:weblibre/features/search_credits/domain/repositories/web_search_settings.dart';
class SearchModeSelector extends ConsumerWidget {
@@ -6,7 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:nullability/nullability.dart';
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
import 'package:weblibre/features/search_credits/domain/repositories/web_search_settings.dart';
import 'package:weblibre/features/web_search/domain/controllers/search_controller.dart';
import 'package:weblibre/features/web_search/domain/entities/captured_page_state.dart';
@@ -4,7 +4,7 @@ import 'package:flutter_material_design_icons/flutter_material_design_icons.dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:intl/locale.dart' as intl;
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
import 'package:weblibre/domain/repositories/locale_resolver.dart';
const _expandableKeys = {'snippet', 'review', 'question'};
@@ -3,7 +3,7 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:search_backend/search_backend.dart';
import 'package:search_protocol/search_protocol.dart';
import 'package:weblibre/features/web_search/domain/controllers/search_controller.dart';
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';