add isolated tab feature

This commit is contained in:
Fabian Freund
2026-02-27 08:29:50 +01:00
parent 3ef567cc19
commit d24675094d
84 changed files with 3783 additions and 513 deletions
@@ -34,6 +34,8 @@ import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
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/data/entities/isolation_context.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode.dart';
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/domain/repositories/tab.dart';
@@ -78,13 +80,23 @@ class TabStates extends _$TabStates {
resolvedTitle = contentState.title;
}
// Infer tabMode from context ID if not already set and context is isolated
final inferredTabMode = switch (current.tabMode) {
IsolatedTabMode() => current.tabMode,
_ when isIsolatedContextId(contentState.contextId) => TabMode.isolated(
contentState.contextId!,
),
_ when contentState.isPrivate => TabMode.private,
_ => TabMode.regular,
};
final newState = current.copyWith(
parentId: contentState.parentId,
contextId: contentState.contextId,
url: url,
title: resolvedTitle,
progress: contentState.progress,
isPrivate: contentState.isPrivate,
tabMode: inferredTabMode,
isFullScreen: contentState.isFullScreen,
isLoading: contentState.isLoading,
showToolbarAsExpanded: contentState.showToolbarAsExpanded,
@@ -373,7 +385,9 @@ Future<bool> isTabTunneled(Ref ref, String? tabId) async {
final torSettings = ref.watch(torSettingsWithDefaultsProvider);
if (tabState != null) {
if (tabState.isPrivate) {
// Isolated tabs follow the same proxy rules as regular tabs
// (container-based routing via proxy aliasing)
if (tabState.tabMode is PrivateTabMode) {
return torSettings.proxyPrivateTabsTor;
} else {
switch (torSettings.proxyRegularTabsMode) {
@@ -402,13 +416,9 @@ TabState? selectedTabState(Ref ref) {
@Riverpod()
TabType? selectedTabType(Ref ref) {
final isPrivate = ref.watch(
selectedTabStateProvider.select((value) => value?.isPrivate),
);
final selectedState = ref.watch(selectedTabStateProvider);
return isPrivate.mapNotNull(
(isCurrentPrivate) => isCurrentPrivate ? TabType.private : TabType.regular,
);
return selectedState?.tabMode.toTabType();
}
@Riverpod()
@@ -41,7 +41,7 @@ final class TabStatesProvider
}
}
String _$tabStatesHash() => r'975de1242f42e2017754dc560125788b83ad8b72';
String _$tabStatesHash() => r'0fd97193ff963006e1943436b25b025dd3885c65';
abstract class _$TabStates extends $Notifier<Map<String, TabState>> {
Map<String, TabState> build();
@@ -258,7 +258,7 @@ final class IsTabTunneledProvider
}
}
String _$isTabTunneledHash() => r'55a42ccb73d1921eed27d32f6da3a54680d4ac8c';
String _$isTabTunneledHash() => r'7265f5e6f32056846d3df38f48476d10c3a70bac';
final class IsTabTunneledFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<bool>, String?> {
@@ -358,7 +358,7 @@ final class SelectedTabTypeProvider
}
}
String _$selectedTabTypeHash() => r'53093fc6db8becde7500163661e087fb0a2eb955';
String _$selectedTabTypeHash() => r'fe14b5c9f81d8f5859ae9d758e440c42908e8a54';
@ProviderFor(selectedTabContainerId)
final selectedTabContainerIdProvider = SelectedTabContainerIdProvider._();