From 305bead1102e9638fac160f31bfd66f55131b6c4 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Sat, 11 Nov 2023 23:10:58 +0330 Subject: [PATCH] Add service mode and strict route --- assets/translations/strings_en.i18n.json | 11 ++-- assets/translations/strings_fa.i18n.json | 11 ++-- assets/translations/strings_ru.i18n.json | 11 ++-- assets/translations/strings_zh.i18n.json | 13 +++-- lib/data/repository/config_options_store.dart | 58 ++++++++----------- lib/domain/singbox/config_options.dart | 1 + lib/domain/singbox/core_mode.dart | 13 ----- lib/domain/singbox/service_mode.dart | 24 ++++++++ lib/domain/singbox/singbox.dart | 2 +- .../settings/view/config_options_page.dart | 57 ++++++++++++++---- .../system_tray/system_tray_controller.dart | 14 ++--- libcore | 2 +- 12 files changed, 132 insertions(+), 85 deletions(-) delete mode 100644 lib/domain/singbox/core_mode.dart create mode 100644 lib/domain/singbox/service_mode.dart diff --git a/assets/translations/strings_en.i18n.json b/assets/translations/strings_en.i18n.json index 57f3d155..ad62901c 100644 --- a/assets/translations/strings_en.i18n.json +++ b/assets/translations/strings_en.i18n.json @@ -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": { diff --git a/assets/translations/strings_fa.i18n.json b/assets/translations/strings_fa.i18n.json index e205cadf..6e4f06de 100644 --- a/assets/translations/strings_fa.i18n.json +++ b/assets/translations/strings_fa.i18n.json @@ -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": { diff --git a/assets/translations/strings_ru.i18n.json b/assets/translations/strings_ru.i18n.json index c96469c2..ecc70db2 100644 --- a/assets/translations/strings_ru.i18n.json +++ b/assets/translations/strings_ru.i18n.json @@ -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": { diff --git a/assets/translations/strings_zh.i18n.json b/assets/translations/strings_zh.i18n.json index e4a7b076..54e5030d 100644 --- a/assets/translations/strings_zh.i18n.json +++ b/assets/translations/strings_zh.i18n.json @@ -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": { diff --git a/lib/data/repository/config_options_store.dart b/lib/data/repository/config_options_store.dart index 16234849..55c7455c 100644 --- a/lib/data/repository/config_options_store.dart +++ b/lib/data/repository/config_options_store.dart @@ -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 update(CoreMode value) { + Future 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, + ); } diff --git a/lib/domain/singbox/config_options.dart b/lib/domain/singbox/config_options.dart index ca51fe22..c7fcbe1b 100644 --- a/lib/domain/singbox/config_options.dart +++ b/lib/domain/singbox/config_options.dart @@ -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)) diff --git a/lib/domain/singbox/core_mode.dart b/lib/domain/singbox/core_mode.dart deleted file mode 100644 index 53386892..00000000 --- a/lib/domain/singbox/core_mode.dart +++ /dev/null @@ -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, - }; -} diff --git a/lib/domain/singbox/service_mode.dart b/lib/domain/singbox/service_mode.dart new file mode 100644 index 00000000..34481e2d --- /dev/null +++ b/lib/domain/singbox/service_mode.dart @@ -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 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, + }; +} diff --git a/lib/domain/singbox/singbox.dart b/lib/domain/singbox/singbox.dart index 06924b10..0ca7decc 100644 --- a/lib/domain/singbox/singbox.dart +++ b/lib/domain/singbox/singbox.dart @@ -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'; diff --git a/lib/features/settings/view/config_options_page.dart b/lib/features/settings/view/config_options_page.dart index a1994f13..a4064fe2 100644 --- a/lib/features/settings/view/config_options_page.dart +++ b/lib/features/settings/view/config_options_page.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), diff --git a/lib/features/system_tray/system_tray_controller.dart b/lib/features/system_tray/system_tray_controller.dart index 28671deb..92d179fe 100644 --- a/lib/features/system_tray/system_tray_controller.dart +++ b/lib/features/system_tray/system_tray_controller.dart @@ -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); }, ), diff --git a/libcore b/libcore index f89ede49..5c8b283d 160000 --- a/libcore +++ b/libcore @@ -1 +1 @@ -Subproject commit f89ede4990ee72b00755020964bc06135b115eb9 +Subproject commit 5c8b283d9cd84a4b1412dd65572ae039a822de78