Add service mode and strict route
This commit is contained in:
@@ -164,10 +164,10 @@
|
||||
"clearSelection": "Clear selection"
|
||||
},
|
||||
"config": {
|
||||
"mode": "Mode",
|
||||
"modes": {
|
||||
"none": "None",
|
||||
"serviceMode": "Service Mode",
|
||||
"serviceModes": {
|
||||
"proxy": "Proxy",
|
||||
"systemProxy": "System Proxy",
|
||||
"tun": "VPN"
|
||||
},
|
||||
"section": {
|
||||
@@ -199,7 +199,10 @@
|
||||
"enableClashApi": "Enable Clash API",
|
||||
"clashApiPort": "Clash API Port",
|
||||
"enableTun": "Enable TUN",
|
||||
"setSystemProxy": "Set System Proxy"
|
||||
"setSystemProxy": "Set System Proxy",
|
||||
"enableFakeDns": "Enable Fake DNS",
|
||||
"bypassLan": "Bypass Lan",
|
||||
"strictRoute": "Strict Route"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -164,10 +164,10 @@
|
||||
"clearSelection": "حذف انتخابها"
|
||||
},
|
||||
"config": {
|
||||
"mode": "حالت",
|
||||
"modes": {
|
||||
"none": "هیچ یک",
|
||||
"serviceMode": "حالت سرویس",
|
||||
"serviceModes": {
|
||||
"proxy": "پروکسی",
|
||||
"systemProxy": "پروکسی سیستم",
|
||||
"tun": "VPN"
|
||||
},
|
||||
"section": {
|
||||
@@ -199,7 +199,10 @@
|
||||
"enableClashApi": "فعالسازی کلش",
|
||||
"clashApiPort": "پورت کلش",
|
||||
"enableTun": "فعال سازی تونل",
|
||||
"setSystemProxy": "تنظیم پروکسی سیستم"
|
||||
"setSystemProxy": "تنظیم پروکسی سیستم",
|
||||
"enableFakeDns": "Enable Fake DNS",
|
||||
"bypassLan": "Bypass Lan",
|
||||
"strictRoute": "Strict Route"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -164,10 +164,10 @@
|
||||
"clearSelection": "Очистить выбор"
|
||||
},
|
||||
"config": {
|
||||
"mode": "Режим",
|
||||
"modes": {
|
||||
"none": "Нет",
|
||||
"serviceMode": "Сервисный режим",
|
||||
"serviceModes": {
|
||||
"proxy": "Прокси",
|
||||
"systemProxy": "Системный прокси",
|
||||
"tun": "VPN"
|
||||
},
|
||||
"section": {
|
||||
@@ -199,7 +199,10 @@
|
||||
"enableClashApi": "Использовать Clash API",
|
||||
"clashApiPort": "Порт Clash API",
|
||||
"enableTun": "Использовать TUN",
|
||||
"setSystemProxy": "Установить системный прокси"
|
||||
"setSystemProxy": "Установить системный прокси",
|
||||
"enableFakeDns": "Enable Fake DNS",
|
||||
"bypassLan": "Bypass Lan",
|
||||
"strictRoute": "Strict Route"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -164,10 +164,10 @@
|
||||
"clearSelection": "清空选项"
|
||||
},
|
||||
"config": {
|
||||
"mode": "模式",
|
||||
"modes": {
|
||||
"none": "无",
|
||||
"proxy": "代理",
|
||||
"serviceMode": "服务方式",
|
||||
"serviceModes": {
|
||||
"proxy": "代理人",
|
||||
"systemProxy": "系统代理",
|
||||
"tun": "VPN"
|
||||
},
|
||||
"section": {
|
||||
@@ -199,7 +199,10 @@
|
||||
"enableClashApi": "启用 Clash API",
|
||||
"clashApiPort": "Clash API 端口",
|
||||
"enableTun": "启用 TUN",
|
||||
"setSystemProxy": "设置系统代理"
|
||||
"setSystemProxy": "设置系统代理",
|
||||
"enableFakeDns": "Enable Fake DNS",
|
||||
"bypassLan": "Bypass Lan",
|
||||
"strictRoute": "Strict Route"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:hiddify/core/prefs/prefs.dart';
|
||||
import 'package:hiddify/data/data_providers.dart';
|
||||
import 'package:hiddify/domain/singbox/singbox.dart';
|
||||
import 'package:hiddify/utils/pref_notifier.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'config_options_store.g.dart';
|
||||
@@ -13,19 +12,19 @@ bool _debugConfigBuilder = false;
|
||||
final _default = ConfigOptions.initial;
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class CoreModeStore extends _$CoreModeStore {
|
||||
class ServiceModeStore extends _$ServiceModeStore {
|
||||
late final _pref = Pref(
|
||||
ref.watch(sharedPreferencesProvider),
|
||||
"mode",
|
||||
PlatformUtils.isDesktop ? CoreMode.proxy : CoreMode.tun,
|
||||
mapFrom: CoreMode.values.byName,
|
||||
"service-mode",
|
||||
ServiceMode.defaultMode,
|
||||
mapFrom: ServiceMode.values.byName,
|
||||
mapTo: (value) => value.name,
|
||||
);
|
||||
|
||||
@override
|
||||
CoreMode build() => _pref.getValue();
|
||||
ServiceMode build() => _pref.getValue();
|
||||
|
||||
Future<void> update(CoreMode value) {
|
||||
Future<void> update(ServiceMode value) {
|
||||
state = value;
|
||||
return _pref.update(value);
|
||||
}
|
||||
@@ -83,9 +82,14 @@ final enableClashApiStore =
|
||||
PrefNotifier.provider("enable-clash-api", _default.enableClashApi);
|
||||
final clashApiPortStore =
|
||||
PrefNotifier.provider("clash-api-port", _default.clashApiPort);
|
||||
final enableTunStore = PrefNotifier.provider("enable-tun", _default.enableTun);
|
||||
final setSystemProxyStore =
|
||||
PrefNotifier.provider("set-system-proxy", _default.setSystemProxy);
|
||||
// final enableTunStore = PrefNotifier.provider("enable-tun", _default.enableTun);
|
||||
// final setSystemProxyStore =
|
||||
// PrefNotifier.provider("set-system-proxy", _default.setSystemProxy);
|
||||
final strictRouteStore =
|
||||
PrefNotifier.provider("strict-route", _default.strictRoute);
|
||||
final bypassLanStore = PrefNotifier.provider("bypass-lan", _default.bypassLan);
|
||||
final enableFakeDnsStore =
|
||||
PrefNotifier.provider("enable-fake-dns", _default.enableFakeDns);
|
||||
|
||||
// HACK temporary
|
||||
@riverpod
|
||||
@@ -138,38 +142,24 @@ ConfigOptions configPreferences(ConfigPreferencesRef ref) {
|
||||
localDnsPort: ref.watch(localDnsPortStore),
|
||||
tunImplementation: ref.watch(tunImplementationStore),
|
||||
mtu: ref.watch(mtuStore),
|
||||
strictRoute: ref.watch(strictRouteStore),
|
||||
connectionTestUrl: ref.watch(connectionTestUrlStore),
|
||||
urlTestInterval: ref.watch(urlTestIntervalStore),
|
||||
enableClashApi: ref.watch(enableClashApiStore),
|
||||
clashApiPort: ref.watch(clashApiPortStore),
|
||||
enableTun: ref.watch(enableTunStore),
|
||||
setSystemProxy: ref.watch(setSystemProxyStore),
|
||||
// enableTun: ref.watch(enableTunStore),
|
||||
// setSystemProxy: ref.watch(setSystemProxyStore),
|
||||
bypassLan: ref.watch(bypassLanStore),
|
||||
enableFakeDns: ref.watch(enableFakeDnsStore),
|
||||
rules: ref.watch(rulesProvider),
|
||||
);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
ConfigOptions configOptions(ConfigOptionsRef ref) {
|
||||
final mode = ref.watch(coreModeStoreProvider);
|
||||
return ConfigOptions(
|
||||
executeConfigAsIs: kDebugMode && _debugConfigBuilder,
|
||||
logLevel: ref.watch(logLevelStore),
|
||||
resolveDestination: ref.watch(resolveDestinationStore),
|
||||
ipv6Mode: ref.watch(ipv6ModeStore),
|
||||
remoteDnsAddress: ref.watch(remoteDnsAddressStore),
|
||||
remoteDnsDomainStrategy: ref.watch(remoteDnsDomainStrategyStore),
|
||||
directDnsAddress: ref.watch(directDnsAddressStore),
|
||||
directDnsDomainStrategy: ref.watch(directDnsDomainStrategyStore),
|
||||
mixedPort: ref.watch(mixedPortStore),
|
||||
localDnsPort: ref.watch(localDnsPortStore),
|
||||
tunImplementation: ref.watch(tunImplementationStore),
|
||||
mtu: ref.watch(mtuStore),
|
||||
connectionTestUrl: ref.watch(connectionTestUrlStore),
|
||||
urlTestInterval: ref.watch(urlTestIntervalStore),
|
||||
enableClashApi: ref.watch(enableClashApiStore),
|
||||
clashApiPort: ref.watch(clashApiPortStore),
|
||||
enableTun: mode == CoreMode.tun || ref.watch(enableTunStore),
|
||||
setSystemProxy: mode == CoreMode.proxy || ref.watch(setSystemProxyStore),
|
||||
rules: ref.watch(rulesProvider),
|
||||
);
|
||||
final serviceMode = ref.watch(serviceModeStoreProvider);
|
||||
return ref.watch(configPreferencesProvider).copyWith(
|
||||
enableTun: serviceMode == ServiceMode.tun,
|
||||
setSystemProxy: serviceMode == ServiceMode.systemProxy,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class ConfigOptions with _$ConfigOptions {
|
||||
@Default(6450) int localDnsPort,
|
||||
@Default(TunImplementation.mixed) TunImplementation tunImplementation,
|
||||
@Default(9000) int mtu,
|
||||
@Default(true) bool strictRoute,
|
||||
@Default("http://cp.cloudflare.com/") String connectionTestUrl,
|
||||
@IntervalConverter()
|
||||
@Default(Duration(minutes: 10))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import 'package:hiddify/core/prefs/locale_prefs.dart';
|
||||
|
||||
enum CoreMode {
|
||||
none,
|
||||
proxy,
|
||||
tun;
|
||||
|
||||
String present(TranslationsEn t) => switch (this) {
|
||||
none => t.settings.config.modes.none,
|
||||
proxy => t.settings.config.modes.proxy,
|
||||
tun => t.settings.config.modes.tun,
|
||||
};
|
||||
}
|
||||
24
lib/domain/singbox/service_mode.dart
Normal file
24
lib/domain/singbox/service_mode.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:hiddify/core/prefs/locale_prefs.dart';
|
||||
import 'package:hiddify/utils/platform_utils.dart';
|
||||
|
||||
enum ServiceMode {
|
||||
proxy,
|
||||
systemProxy,
|
||||
tun;
|
||||
|
||||
static ServiceMode get defaultMode =>
|
||||
PlatformUtils.isDesktop ? systemProxy : tun;
|
||||
|
||||
static List<ServiceMode> get choices {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
return values;
|
||||
}
|
||||
return [proxy, tun];
|
||||
}
|
||||
|
||||
String present(TranslationsEn t) => switch (this) {
|
||||
proxy => t.settings.config.serviceModes.proxy,
|
||||
systemProxy => t.settings.config.serviceModes.systemProxy,
|
||||
tun => t.settings.config.serviceModes.tun,
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
export 'box_log.dart';
|
||||
export 'config_options.dart';
|
||||
export 'core_mode.dart';
|
||||
export 'core_status.dart';
|
||||
export 'outbounds.dart';
|
||||
export 'proxy_type.dart';
|
||||
export 'rules.dart';
|
||||
export 'service_mode.dart';
|
||||
export 'singbox_facade.dart';
|
||||
|
||||
@@ -19,6 +19,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
final t = ref.watch(translationsProvider);
|
||||
|
||||
final options = ref.watch(configPreferencesProvider);
|
||||
final serviceMode = ref.watch(serviceModeStoreProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -59,6 +60,11 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(t.settings.config.section.route),
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.bypassLan),
|
||||
// value: options.bypassLan,
|
||||
// onChanged: ref.read(bypassLanStore.notifier).update,
|
||||
// ),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.resolveDestination),
|
||||
value: options.resolveDestination,
|
||||
@@ -141,20 +147,47 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
.update(domainStrategy);
|
||||
},
|
||||
),
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.enableFakeDns),
|
||||
// value: options.enableFakeDns,
|
||||
// onChanged: ref.read(enableFakeDnsStore.notifier).update,
|
||||
// ),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(t.settings.config.section.inbound),
|
||||
if (PlatformUtils.isDesktop) ...[
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.enableTun),
|
||||
value: options.enableTun,
|
||||
onChanged: ref.read(enableTunStore.notifier).update,
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.setSystemProxy),
|
||||
value: options.setSystemProxy,
|
||||
onChanged: ref.read(setSystemProxyStore.notifier).update,
|
||||
),
|
||||
],
|
||||
// if (PlatformUtils.isDesktop) ...[
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.enableTun),
|
||||
// value: options.enableTun,
|
||||
// onChanged: ref.read(enableTunStore.notifier).update,
|
||||
// ),
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.setSystemProxy),
|
||||
// value: options.setSystemProxy,
|
||||
// onChanged: ref.read(setSystemProxyStore.notifier).update,
|
||||
// ),
|
||||
// ],
|
||||
ListTile(
|
||||
title: Text(t.settings.config.serviceMode),
|
||||
subtitle: Text(serviceMode.present(t)),
|
||||
onTap: () async {
|
||||
final pickedMode = await SettingsPickerDialog(
|
||||
title: t.settings.config.serviceMode,
|
||||
selected: serviceMode,
|
||||
options: ServiceMode.choices,
|
||||
getTitle: (e) => e.present(t),
|
||||
resetValue: ServiceMode.defaultMode,
|
||||
).show(context);
|
||||
if (pickedMode == null) return;
|
||||
await ref
|
||||
.read(serviceModeStoreProvider.notifier)
|
||||
.update(pickedMode);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.strictRoute),
|
||||
value: options.strictRoute,
|
||||
onChanged: ref.read(strictRouteStore.notifier).update,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.settings.config.tunImplementation),
|
||||
subtitle: Text(options.tunImplementation.name),
|
||||
|
||||
@@ -31,7 +31,7 @@ class SystemTrayController extends _$SystemTrayController
|
||||
}
|
||||
|
||||
final connection = await ref.watch(connectivityControllerProvider.future);
|
||||
final mode = ref.watch(coreModeStoreProvider);
|
||||
final serviceMode = ref.watch(serviceModeStoreProvider);
|
||||
|
||||
final t = ref.watch(translationsProvider);
|
||||
|
||||
@@ -56,19 +56,19 @@ class SystemTrayController extends _$SystemTrayController
|
||||
onClick: handleClickSetAsSystemProxy,
|
||||
),
|
||||
MenuItem.submenu(
|
||||
label: t.settings.config.mode,
|
||||
label: t.settings.config.serviceMode,
|
||||
submenu: Menu(
|
||||
items: [
|
||||
...CoreMode.values.map(
|
||||
...ServiceMode.values.map(
|
||||
(e) => MenuItem.checkbox(
|
||||
checked: e == mode,
|
||||
checked: e == serviceMode,
|
||||
key: e.name,
|
||||
label: e.present(t),
|
||||
onClick: (menuItem) async {
|
||||
final newMode = CoreMode.values.byName(menuItem.key!);
|
||||
loggy.debug("switching core mode: [$newMode]");
|
||||
final newMode = ServiceMode.values.byName(menuItem.key!);
|
||||
loggy.debug("switching service mode: [$newMode]");
|
||||
await ref
|
||||
.read(coreModeStoreProvider.notifier)
|
||||
.read(serviceModeStoreProvider.notifier)
|
||||
.update(newMode);
|
||||
},
|
||||
),
|
||||
|
||||
2
libcore
2
libcore
Submodule libcore updated: f89ede4990...5c8b283d9c
Reference in New Issue
Block a user