diff --git a/app/lib/features/geckoview/domain/providers/tab_state.dart b/app/lib/features/geckoview/domain/providers/tab_state.dart index d627f413..7a70f8d4 100644 --- a/app/lib/features/geckoview/domain/providers/tab_state.dart +++ b/app/lib/features/geckoview/domain/providers/tab_state.dart @@ -35,8 +35,12 @@ import 'package:weblibre/features/geckoview/domain/providers.dart'; import 'package:weblibre/features/geckoview/domain/providers/selected_tab.dart'; import 'package:weblibre/features/geckoview/features/find_in_page/domain/repositories/find_in_page.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart'; +import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart'; +import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart'; import 'package:weblibre/features/geckoview/utils/image_helper.dart'; +import 'package:weblibre/features/user/data/models/tor_settings.dart'; +import 'package:weblibre/features/user/domain/repositories/tor_settings.dart'; part 'tab_state.g.dart'; @@ -238,6 +242,37 @@ TabState? tabState(Ref ref, String? tabId) { return ref.watch(tabStatesProvider.select((tabs) => tabs[tabId])); } +@Riverpod() +Future isTabTunneled(Ref ref, String? tabId) async { + final tabState = ref.watch(tabStateProvider(tabId)); + final torSettings = ref.watch(torSettingsWithDefaultsProvider); + + if (tabState != null) { + if (tabState.isPrivate) { + return torSettings.proxyPrivateTabsTor; + } else { + switch (torSettings.proxyRegularTabsMode) { + case TorRegularTabProxyMode.container: + final containerId = await ref + .read(tabDataRepositoryProvider.notifier) + .getContainerTabId(tabState.id); + + final containerData = await containerId.mapNotNull( + (containerId) => ref + .read(containerRepositoryProvider.notifier) + .getContainerData(containerId), + ); + + return containerData?.metadata.useProxy ?? false; + case TorRegularTabProxyMode.all: + return true; + } + } + } + + return false; +} + @Riverpod() TabState? selectedTabState(Ref ref) { final tabId = ref.watch(selectedTabProvider); diff --git a/app/lib/features/geckoview/domain/providers/tab_state.g.dart b/app/lib/features/geckoview/domain/providers/tab_state.g.dart index b8ebaf7e..db817ed3 100644 --- a/app/lib/features/geckoview/domain/providers/tab_state.g.dart +++ b/app/lib/features/geckoview/domain/providers/tab_state.g.dart @@ -139,6 +139,75 @@ final class TabStateFamily extends $Family String toString() => r'tabStateProvider'; } +@ProviderFor(isTabTunneled) +const isTabTunneledProvider = IsTabTunneledFamily._(); + +final class IsTabTunneledProvider + extends $FunctionalProvider, bool, FutureOr> + with $FutureModifier, $FutureProvider { + const IsTabTunneledProvider._({ + required IsTabTunneledFamily super.from, + required String? super.argument, + }) : super( + retry: null, + name: r'isTabTunneledProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$isTabTunneledHash(); + + @override + String toString() { + return r'isTabTunneledProvider' + '' + '($argument)'; + } + + @$internal + @override + $FutureProviderElement $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr create(Ref ref) { + final argument = this.argument as String?; + return isTabTunneled(ref, argument); + } + + @override + bool operator ==(Object other) { + return other is IsTabTunneledProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$isTabTunneledHash() => r'fd8ca366b0835eef8aea7ad64453e6a6f2e69e82'; + +final class IsTabTunneledFamily extends $Family + with $FunctionalFamilyOverride, String?> { + const IsTabTunneledFamily._() + : super( + retry: null, + name: r'isTabTunneledProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + IsTabTunneledProvider call(String? tabId) => + IsTabTunneledProvider._(argument: tabId, from: this); + + @override + String toString() => r'isTabTunneledProvider'; +} + @ProviderFor(selectedTabState) const selectedTabStateProvider = SelectedTabStateProvider._(); diff --git a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart index ac37f7f6..3043a61b 100644 --- a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart +++ b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart @@ -35,6 +35,7 @@ class AppBarTitle extends HookConsumerWidget { final theme = Theme.of(context); final tabState = ref.watch(selectedTabStateProvider); + final isTabTuneledAsync = ref.watch(isTabTunneledProvider(tabState?.id)); if (tabState == null) { return const SizedBox.shrink(); @@ -98,6 +99,11 @@ class AppBarTitle extends HookConsumerWidget { ), Row( children: [ + if (isTabTuneledAsync.hasValue && + isTabTuneledAsync.value == true) ...[ + const Icon(MdiIcons.tunnelOutline, size: 14), + const SizedBox(width: 4), + ], icon, const SizedBox(width: 4), Expanded(