Add service mode and strict route

This commit is contained in:
problematicconsumer
2023-11-11 23:10:58 +03:30
parent 5125c1cc13
commit 305bead110
12 changed files with 132 additions and 85 deletions

View File

@@ -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,
);
}

View File

@@ -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))

View File

@@ -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,
};
}

View 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,
};
}

View File

@@ -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';

View File

@@ -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),

View File

@@ -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);
},
),