Add proxy routing and sing-box support
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2026 Fabian Freund.
|
||||
*
|
||||
* This file is part of WebLibre
|
||||
* (see https://weblibre.eu).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||
import 'package:weblibre/features/proxy/data/models/singbox_proxy_profile.dart';
|
||||
import 'package:weblibre/features/proxy/domain/repositories/singbox_proxy_profiles.dart';
|
||||
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
||||
show ProxyProfile;
|
||||
import 'package:weblibre/features/user/data/models/proxy_routing_settings.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/proxy_routing_settings.dart';
|
||||
|
||||
part 'assigned_proxy_profiles.g.dart';
|
||||
|
||||
/// Returns sing-box proxy profiles that have at least one routing assignment:
|
||||
/// global regular-tab routing, private-tab routing, or any container.
|
||||
@Riverpod(keepAlive: true)
|
||||
List<ProxyProfile> assignedSingboxProxyProfiles(Ref ref) {
|
||||
final profiles =
|
||||
ref.watch(singboxProxyProfilesRepositoryProvider).value ?? const [];
|
||||
if (profiles.isEmpty) return const [];
|
||||
|
||||
final routing = ref.watch(proxyRoutingSettingsWithDefaultsProvider);
|
||||
final containers =
|
||||
ref.watch(watchContainersWithCountProvider).value ?? const [];
|
||||
|
||||
final assignedConnectionIds = <String>{
|
||||
if (routing.regularTabsMode == ProxyRegularTabRoutingMode.all &&
|
||||
routing.regularTabsProxyConnectionId != null)
|
||||
routing.regularTabsProxyConnectionId!.encode(),
|
||||
if (routing.privateTabsProxyConnectionId != null)
|
||||
routing.privateTabsProxyConnectionId!.encode(),
|
||||
for (final container in containers)
|
||||
if (container.metadata.proxyConnectionId != null)
|
||||
container.metadata.proxyConnectionId!.encode(),
|
||||
};
|
||||
|
||||
if (assignedConnectionIds.isEmpty) return const [];
|
||||
|
||||
return [
|
||||
for (final profile in profiles)
|
||||
if (assignedConnectionIds.contains(profile.proxyConnectionId)) profile,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'assigned_proxy_profiles.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
/// Returns sing-box proxy profiles that have at least one routing assignment:
|
||||
/// global regular-tab routing, private-tab routing, or any container.
|
||||
|
||||
@ProviderFor(assignedSingboxProxyProfiles)
|
||||
final assignedSingboxProxyProfilesProvider =
|
||||
AssignedSingboxProxyProfilesProvider._();
|
||||
|
||||
/// Returns sing-box proxy profiles that have at least one routing assignment:
|
||||
/// global regular-tab routing, private-tab routing, or any container.
|
||||
|
||||
final class AssignedSingboxProxyProfilesProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
List<ProxyProfile>,
|
||||
List<ProxyProfile>,
|
||||
List<ProxyProfile>
|
||||
>
|
||||
with $Provider<List<ProxyProfile>> {
|
||||
/// Returns sing-box proxy profiles that have at least one routing assignment:
|
||||
/// global regular-tab routing, private-tab routing, or any container.
|
||||
AssignedSingboxProxyProfilesProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'assignedSingboxProxyProfilesProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$assignedSingboxProxyProfilesHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<List<ProxyProfile>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
List<ProxyProfile> create(Ref ref) {
|
||||
return assignedSingboxProxyProfiles(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(List<ProxyProfile> value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<List<ProxyProfile>>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$assignedSingboxProxyProfilesHash() =>
|
||||
r'dbc5c429a3b5e4bff902023d363e568c2f955fc4';
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2026 Fabian Freund.
|
||||
*
|
||||
* This file is part of WebLibre
|
||||
* (see https://weblibre.eu).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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';
|
||||
import 'package:weblibre/features/proxy/data/proxy_connection.dart';
|
||||
import 'package:weblibre/features/proxy/domain/extensions/singbox_proxy_profile_type_x.dart';
|
||||
import 'package:weblibre/features/proxy/domain/repositories/singbox_proxy_profiles.dart';
|
||||
|
||||
part 'proxy_connection_options.g.dart';
|
||||
|
||||
class ProxyConnectionOption with FastEquatable {
|
||||
final ProxyConnectionId id;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
|
||||
ProxyConnectionOption({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get hashParameters => [id, title, subtitle];
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
List<ProxyConnectionOption> proxyConnectionOptions(Ref ref) {
|
||||
final profilesAsync = ref.watch(singboxProxyProfilesRepositoryProvider);
|
||||
profilesAsync.whenOrNull(
|
||||
error: (error, stackTrace) => logger.e(
|
||||
'Failed to load sing-box proxy profiles for connection picker',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
),
|
||||
);
|
||||
|
||||
final singboxProfiles = profilesAsync.value ?? const [];
|
||||
|
||||
return [
|
||||
ProxyConnectionOption(
|
||||
id: const TorProxyConnectionId(),
|
||||
title: 'Tor',
|
||||
subtitle: 'Route through the Tor network',
|
||||
),
|
||||
for (final profile in singboxProfiles)
|
||||
ProxyConnectionOption(
|
||||
id: profile.proxyConnection,
|
||||
title: profile.name,
|
||||
subtitle: profile.type.label,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
String proxyConnectionTitle(
|
||||
List<ProxyConnectionOption> options,
|
||||
ProxyConnectionId proxyConnectionId,
|
||||
) {
|
||||
for (final option in options) {
|
||||
if (option.id == proxyConnectionId) {
|
||||
return option.title;
|
||||
}
|
||||
}
|
||||
|
||||
return 'Unknown proxy';
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'proxy_connection_options.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(proxyConnectionOptions)
|
||||
final proxyConnectionOptionsProvider = ProxyConnectionOptionsProvider._();
|
||||
|
||||
final class ProxyConnectionOptionsProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
List<ProxyConnectionOption>,
|
||||
List<ProxyConnectionOption>,
|
||||
List<ProxyConnectionOption>
|
||||
>
|
||||
with $Provider<List<ProxyConnectionOption>> {
|
||||
ProxyConnectionOptionsProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'proxyConnectionOptionsProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$proxyConnectionOptionsHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<List<ProxyConnectionOption>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
List<ProxyConnectionOption> create(Ref ref) {
|
||||
return proxyConnectionOptions(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(List<ProxyConnectionOption> value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<List<ProxyConnectionOption>>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$proxyConnectionOptionsHash() =>
|
||||
r'7832968f74acd98189110cf926208e694a20d55a';
|
||||
Reference in New Issue
Block a user