add warp config, update to flutter 1.22
This commit is contained in:
@@ -51,8 +51,7 @@ abstract class ConfigOptions {
|
||||
validator: (value) => value.isNotBlank,
|
||||
);
|
||||
|
||||
static final remoteDnsDomainStrategy =
|
||||
PreferencesNotifier.create<DomainStrategy, String>(
|
||||
static final remoteDnsDomainStrategy = PreferencesNotifier.create<DomainStrategy, String>(
|
||||
"remote-dns-domain-strategy",
|
||||
DomainStrategy.auto,
|
||||
mapFrom: (value) => DomainStrategy.values.firstWhere((e) => e.key == value),
|
||||
@@ -65,8 +64,7 @@ abstract class ConfigOptions {
|
||||
validator: (value) => value.isNotBlank,
|
||||
);
|
||||
|
||||
static final directDnsDomainStrategy =
|
||||
PreferencesNotifier.create<DomainStrategy, String>(
|
||||
static final directDnsDomainStrategy = PreferencesNotifier.create<DomainStrategy, String>(
|
||||
"direct-dns-domain-strategy",
|
||||
DomainStrategy.auto,
|
||||
mapFrom: (value) => DomainStrategy.values.firstWhere((e) => e.key == value),
|
||||
@@ -91,8 +89,7 @@ abstract class ConfigOptions {
|
||||
validator: (value) => isPort(value.toString()),
|
||||
);
|
||||
|
||||
static final tunImplementation =
|
||||
PreferencesNotifier.create<TunImplementation, String>(
|
||||
static final tunImplementation = PreferencesNotifier.create<TunImplementation, String>(
|
||||
"tun-implementation",
|
||||
TunImplementation.mixed,
|
||||
mapFrom: TunImplementation.values.byName,
|
||||
@@ -101,8 +98,7 @@ abstract class ConfigOptions {
|
||||
|
||||
static final mtu = PreferencesNotifier.create<int, int>("mtu", 9000);
|
||||
|
||||
static final strictRoute =
|
||||
PreferencesNotifier.create<bool, bool>("strict-route", true);
|
||||
static final strictRoute = PreferencesNotifier.create<bool, bool>("strict-route", true);
|
||||
|
||||
static final connectionTestUrl = PreferencesNotifier.create<String, String>(
|
||||
"connection-test-url",
|
||||
@@ -128,8 +124,7 @@ abstract class ConfigOptions {
|
||||
validator: (value) => isPort(value.toString()),
|
||||
);
|
||||
|
||||
static final bypassLan =
|
||||
PreferencesNotifier.create<bool, bool>("bypass-lan", false);
|
||||
static final bypassLan = PreferencesNotifier.create<bool, bool>("bypass-lan", false);
|
||||
|
||||
static final allowConnectionFromLan = PreferencesNotifier.create<bool, bool>(
|
||||
"allow-connection-from-lan",
|
||||
@@ -156,16 +151,14 @@ abstract class ConfigOptions {
|
||||
false,
|
||||
);
|
||||
|
||||
static final tlsFragmentSize =
|
||||
PreferencesNotifier.create<OptionalRange, String>(
|
||||
static final tlsFragmentSize = PreferencesNotifier.create<OptionalRange, String>(
|
||||
"tls-fragment-size",
|
||||
const OptionalRange(min: 1, max: 500),
|
||||
mapFrom: OptionalRange.parse,
|
||||
mapTo: const OptionalRangeJsonConverter().toJson,
|
||||
);
|
||||
|
||||
static final tlsFragmentSleep =
|
||||
PreferencesNotifier.create<OptionalRange, String>(
|
||||
static final tlsFragmentSleep = PreferencesNotifier.create<OptionalRange, String>(
|
||||
"tls-fragment-sleep",
|
||||
const OptionalRange(min: 0, max: 500),
|
||||
mapFrom: OptionalRange.parse,
|
||||
@@ -182,8 +175,7 @@ abstract class ConfigOptions {
|
||||
false,
|
||||
);
|
||||
|
||||
static final tlsPaddingSize =
|
||||
PreferencesNotifier.create<OptionalRange, String>(
|
||||
static final tlsPaddingSize = PreferencesNotifier.create<OptionalRange, String>(
|
||||
"tls-padding-size",
|
||||
const OptionalRange(min: 1, max: 1500),
|
||||
mapFrom: OptionalRange.parse,
|
||||
@@ -218,8 +210,7 @@ abstract class ConfigOptions {
|
||||
false,
|
||||
);
|
||||
|
||||
static final warpDetourMode =
|
||||
PreferencesNotifier.create<WarpDetourMode, String>(
|
||||
static final warpDetourMode = PreferencesNotifier.create<WarpDetourMode, String>(
|
||||
"warp-detour-mode",
|
||||
WarpDetourMode.proxyOverWarp,
|
||||
mapFrom: WarpDetourMode.values.byName,
|
||||
@@ -230,16 +221,28 @@ abstract class ConfigOptions {
|
||||
"warp-license-key",
|
||||
"",
|
||||
);
|
||||
static final warp2LicenseKey = PreferencesNotifier.create<String, String>(
|
||||
"warp2s-license-key",
|
||||
"",
|
||||
);
|
||||
|
||||
static final warpAccountId = PreferencesNotifier.create<String, String>(
|
||||
"warp-account-id",
|
||||
"",
|
||||
);
|
||||
static final warp2AccountId = PreferencesNotifier.create<String, String>(
|
||||
"warp2-account-id",
|
||||
"",
|
||||
);
|
||||
|
||||
static final warpAccessToken = PreferencesNotifier.create<String, String>(
|
||||
"warp-access-token",
|
||||
"",
|
||||
);
|
||||
static final warp2AccessToken = PreferencesNotifier.create<String, String>(
|
||||
"warp2-access-token",
|
||||
"",
|
||||
);
|
||||
|
||||
static final warpCleanIp = PreferencesNotifier.create<String, String>(
|
||||
"warp-clean-ip",
|
||||
@@ -259,8 +262,7 @@ abstract class ConfigOptions {
|
||||
mapTo: const OptionalRangeJsonConverter().toJson,
|
||||
);
|
||||
|
||||
static final warpNoiseDelay =
|
||||
PreferencesNotifier.create<OptionalRange, String>(
|
||||
static final warpNoiseDelay = PreferencesNotifier.create<OptionalRange, String>(
|
||||
"warp-noise-delay",
|
||||
const OptionalRange(min: 20, max: 200),
|
||||
mapFrom: (value) => OptionalRange.parse(value, allowEmpty: true),
|
||||
@@ -271,6 +273,10 @@ abstract class ConfigOptions {
|
||||
"warp-wireguard-config",
|
||||
"",
|
||||
);
|
||||
static final warp2WireguardConfig = PreferencesNotifier.create<String, String>(
|
||||
"warp2-wireguard-config",
|
||||
"",
|
||||
);
|
||||
|
||||
static final hasExperimentalFeatures = Provider.autoDispose<bool>(
|
||||
(ref) {
|
||||
@@ -278,13 +284,7 @@ abstract class ConfigOptions {
|
||||
if (PlatformUtils.isDesktop && mode == ServiceMode.tun) {
|
||||
return true;
|
||||
}
|
||||
if (ref.watch(enableTlsFragment) ||
|
||||
ref.watch(enableTlsMixedSniCase) ||
|
||||
ref.watch(enableTlsPadding) ||
|
||||
ref.watch(enableMux) ||
|
||||
ref.watch(enableWarp) ||
|
||||
ref.watch(bypassLan) ||
|
||||
ref.watch(allowConnectionFromLan)) {
|
||||
if (ref.watch(enableTlsFragment) || ref.watch(enableTlsMixedSniCase) || ref.watch(enableTlsPadding) || ref.watch(enableMux) || ref.watch(enableWarp) || ref.watch(bypassLan) || ref.watch(allowConnectionFromLan)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -298,10 +298,13 @@ abstract class ConfigOptions {
|
||||
"warp.access-token",
|
||||
"warp.account-id",
|
||||
"warp.wireguard-config",
|
||||
"warp2.license-key",
|
||||
"warp2.access-token",
|
||||
"warp2.account-id",
|
||||
"warp2.wireguard-config",
|
||||
};
|
||||
|
||||
static final Map<String, StateNotifierProvider<PreferencesNotifier, dynamic>>
|
||||
preferences = {
|
||||
static final Map<String, StateNotifierProvider<PreferencesNotifier, dynamic>> preferences = {
|
||||
"service-mode": serviceMode,
|
||||
"log-level": logLevel,
|
||||
"resolve-destination": resolveDestination,
|
||||
@@ -348,6 +351,10 @@ abstract class ConfigOptions {
|
||||
"warp.noise": warpNoise,
|
||||
"warp.noise-delay": warpNoiseDelay,
|
||||
"warp.wireguard-config": warpWireguardConfig,
|
||||
"warp2.license-key": warp2LicenseKey,
|
||||
"warp2.account-id": warp2AccountId,
|
||||
"warp2.access-token": warp2AccessToken,
|
||||
"warp2.wireguard-config": warp2WireguardConfig,
|
||||
};
|
||||
|
||||
static final singboxConfigOptions = FutureProvider<SingboxConfigOption>(
|
||||
@@ -386,8 +393,7 @@ abstract class ConfigOptions {
|
||||
};
|
||||
|
||||
final geoAssetsRepo = await ref.watch(geoAssetRepositoryProvider.future);
|
||||
final geoAssets =
|
||||
await geoAssetsRepo.getActivePair().getOrElse((l) => throw l).run();
|
||||
final geoAssets = await geoAssetsRepo.getActivePair().getOrElse((l) => throw l).run();
|
||||
|
||||
final mode = ref.watch(serviceMode);
|
||||
return SingboxConfigOption(
|
||||
@@ -443,6 +449,18 @@ abstract class ConfigOptions {
|
||||
noise: ref.watch(warpNoise),
|
||||
noiseDelay: ref.watch(warpNoiseDelay),
|
||||
),
|
||||
warp2: SingboxWarpOption(
|
||||
enable: ref.watch(enableWarp),
|
||||
mode: ref.watch(warpDetourMode),
|
||||
wireguardConfig: ref.watch(warp2WireguardConfig),
|
||||
licenseKey: ref.watch(warp2LicenseKey),
|
||||
accountId: ref.watch(warp2AccountId),
|
||||
accessToken: ref.watch(warp2AccessToken),
|
||||
cleanIp: ref.watch(warpCleanIp),
|
||||
cleanPort: ref.watch(warpPort),
|
||||
noise: ref.watch(warpNoise),
|
||||
noiseDelay: ref.watch(warpNoiseDelay),
|
||||
),
|
||||
geoipPath: ref.watch(geoAssetPathResolverProvider).relativePath(
|
||||
geoAssets.geoip.providerName,
|
||||
geoAssets.geoip.fileName,
|
||||
@@ -470,8 +488,7 @@ class ConfigOptionRepository with ExceptionHandler, InfraLogger {
|
||||
final GeoAssetRepository geoAssetRepository;
|
||||
final GeoAssetPathResolver geoAssetPathResolver;
|
||||
|
||||
TaskEither<ConfigOptionFailure, SingboxConfigOption>
|
||||
getFullSingboxConfigOption() {
|
||||
TaskEither<ConfigOptionFailure, SingboxConfigOption> getFullSingboxConfigOption() {
|
||||
return exceptionHandler(
|
||||
() async {
|
||||
return right(await getConfigOptions());
|
||||
|
||||
@@ -26,20 +26,14 @@ class WarpOptionNotifier extends _$WarpOptionNotifier with AppLogger {
|
||||
|
||||
return WarpOptions(
|
||||
consentGiven: consent,
|
||||
configGeneration: hasWarpConfig
|
||||
? const AsyncValue.data("")
|
||||
: AsyncError(const MissingWarpConfigFailure(), StackTrace.current),
|
||||
configGeneration: hasWarpConfig ? const AsyncValue.data("") : AsyncError(const MissingWarpConfigFailure(), StackTrace.current),
|
||||
);
|
||||
}
|
||||
|
||||
SharedPreferences get _prefs =>
|
||||
ref.read(sharedPreferencesProvider).requireValue;
|
||||
SharedPreferences get _prefs => ref.read(sharedPreferencesProvider).requireValue;
|
||||
|
||||
Future<void> agree() async {
|
||||
await ref
|
||||
.read(sharedPreferencesProvider)
|
||||
.requireValue
|
||||
.setBool(warpConsentGiven, true);
|
||||
await ref.read(sharedPreferencesProvider).requireValue.setBool(warpConsentGiven, true);
|
||||
state = state.copyWith(consentGiven: true);
|
||||
await generateWarpConfig();
|
||||
}
|
||||
@@ -59,15 +53,33 @@ class WarpOptionNotifier extends _$WarpOptionNotifier with AppLogger {
|
||||
.getOrElse((l) => throw l)
|
||||
.run();
|
||||
|
||||
await ref
|
||||
.read(ConfigOptions.warpAccountId.notifier)
|
||||
.update(warp.accountId);
|
||||
await ref
|
||||
.read(ConfigOptions.warpAccessToken.notifier)
|
||||
.update(warp.accessToken);
|
||||
await ref
|
||||
.read(ConfigOptions.warpWireguardConfig.notifier)
|
||||
.update(warp.wireguardConfig);
|
||||
await ref.read(ConfigOptions.warpAccountId.notifier).update(warp.accountId);
|
||||
await ref.read(ConfigOptions.warpAccessToken.notifier).update(warp.accessToken);
|
||||
await ref.read(ConfigOptions.warpWireguardConfig.notifier).update(warp.wireguardConfig);
|
||||
return warp.log;
|
||||
});
|
||||
|
||||
state = state.copyWith(configGeneration: result);
|
||||
}
|
||||
|
||||
Future<void> generateWarp2Config() async {
|
||||
if (state.configGeneration.isLoading) return;
|
||||
state = state.copyWith(configGeneration: const AsyncLoading());
|
||||
|
||||
final result = await AsyncValue.guard(() async {
|
||||
final warp = await ref
|
||||
.read(singboxServiceProvider)
|
||||
.generateWarpConfig(
|
||||
licenseKey: ref.read(ConfigOptions.warpLicenseKey),
|
||||
previousAccountId: ref.read(ConfigOptions.warp2AccountId),
|
||||
previousAccessToken: ref.read(ConfigOptions.warp2AccessToken),
|
||||
)
|
||||
.getOrElse((l) => throw l)
|
||||
.run();
|
||||
|
||||
await ref.read(ConfigOptions.warp2AccountId.notifier).update(warp.accountId);
|
||||
await ref.read(ConfigOptions.warp2AccessToken.notifier).update(warp.accessToken);
|
||||
await ref.read(ConfigOptions.warp2WireguardConfig.notifier).update(warp.wireguardConfig);
|
||||
return warp.log;
|
||||
});
|
||||
|
||||
|
||||
@@ -23,17 +23,20 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:humanizer/humanizer.dart';
|
||||
|
||||
enum ConfigOptionSection {
|
||||
warp;
|
||||
warp,
|
||||
fragment;
|
||||
|
||||
static final _warpKey = GlobalKey(debugLabel: "warp-section-key");
|
||||
static final _fragmentKey = GlobalKey(debugLabel: "fragment-section-key");
|
||||
|
||||
GlobalKey get key => switch (this) { _ => _warpKey };
|
||||
GlobalKey get key => switch (this) {
|
||||
ConfigOptionSection.warp => _warpKey,
|
||||
ConfigOptionSection.fragment => _fragmentKey,
|
||||
};
|
||||
}
|
||||
|
||||
class ConfigOptionsPage extends HookConsumerWidget {
|
||||
ConfigOptionsPage({super.key, String? section})
|
||||
: section =
|
||||
section != null ? ConfigOptionSection.values.byName(section) : null;
|
||||
ConfigOptionsPage({super.key, String? section}) : section = section != null ? ConfigOptionSection.values.byName(section) : null;
|
||||
|
||||
final ConfigOptionSection? section;
|
||||
|
||||
@@ -47,14 +50,10 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
if (section != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) {
|
||||
final box =
|
||||
section!.key.currentContext?.findRenderObject() as RenderBox?;
|
||||
final box = section!.key.currentContext?.findRenderObject() as RenderBox?;
|
||||
final offset = box?.localToGlobal(Offset.zero);
|
||||
if (offset == null) return;
|
||||
final height = scrollController.offset +
|
||||
offset.dy -
|
||||
MediaQueryData.fromView(View.of(context)).padding.top -
|
||||
kToolbarHeight;
|
||||
final height = scrollController.offset + offset.dy - MediaQueryData.fromView(View.of(context)).padding.top - kToolbarHeight;
|
||||
scrollController.animateTo(
|
||||
height,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
@@ -83,36 +82,26 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
onTap: () async => ref
|
||||
.read(configOptionNotifierProvider.notifier)
|
||||
.exportJsonToClipboard()
|
||||
.then((success) {
|
||||
onTap: () async => ref.read(configOptionNotifierProvider.notifier).exportJsonToClipboard().then((success) {
|
||||
if (success) {
|
||||
ref
|
||||
.read(inAppNotificationControllerProvider)
|
||||
.showSuccessToast(
|
||||
ref.read(inAppNotificationControllerProvider).showSuccessToast(
|
||||
t.general.clipboardExportSuccessMsg,
|
||||
);
|
||||
}
|
||||
}),
|
||||
child: Text(t.settings.exportOptions),
|
||||
),
|
||||
if (ref.watch(debugModeNotifierProvider))
|
||||
PopupMenuItem(
|
||||
onTap: () async => ref
|
||||
.read(configOptionNotifierProvider.notifier)
|
||||
.exportJsonToClipboard(excludePrivate: false)
|
||||
.then((success) {
|
||||
if (success) {
|
||||
ref
|
||||
.read(inAppNotificationControllerProvider)
|
||||
.showSuccessToast(
|
||||
t.general.clipboardExportSuccessMsg,
|
||||
);
|
||||
}
|
||||
}),
|
||||
child: Text(t.settings.exportAllOptions),
|
||||
),
|
||||
// if (ref.watch(debugModeNotifierProvider))
|
||||
PopupMenuItem(
|
||||
onTap: () async => ref.read(configOptionNotifierProvider.notifier).exportJsonToClipboard(excludePrivate: false).then((success) {
|
||||
if (success) {
|
||||
ref.read(inAppNotificationControllerProvider).showSuccessToast(
|
||||
t.general.clipboardExportSuccessMsg,
|
||||
);
|
||||
}
|
||||
}),
|
||||
child: Text(t.settings.exportAllOptions),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
final shouldImport = await showConfirmationDialog(
|
||||
@@ -121,9 +110,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
message: t.settings.importOptionsMsg,
|
||||
);
|
||||
if (shouldImport) {
|
||||
await ref
|
||||
.read(configOptionNotifierProvider.notifier)
|
||||
.importFromClipboard();
|
||||
await ref.read(configOptionNotifierProvider.notifier).importFromClipboard();
|
||||
}
|
||||
},
|
||||
child: Text(t.settings.importOptions),
|
||||
@@ -131,9 +118,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
PopupMenuItem(
|
||||
child: Text(t.config.resetBtn),
|
||||
onTap: () async {
|
||||
await ref
|
||||
.read(configOptionNotifierProvider.notifier)
|
||||
.resetOption();
|
||||
await ref.read(configOptionNotifierProvider.notifier).resetOption();
|
||||
},
|
||||
),
|
||||
];
|
||||
@@ -158,15 +143,12 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SwitchListTile(
|
||||
title: Text(experimental(t.config.bypassLan)),
|
||||
value: ref.watch(ConfigOptions.bypassLan),
|
||||
onChanged:
|
||||
ref.watch(ConfigOptions.bypassLan.notifier).update,
|
||||
onChanged: ref.watch(ConfigOptions.bypassLan.notifier).update,
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.config.resolveDestination),
|
||||
value: ref.watch(ConfigOptions.resolveDestination),
|
||||
onChanged: ref
|
||||
.watch(ConfigOptions.resolveDestination.notifier)
|
||||
.update,
|
||||
onChanged: ref.watch(ConfigOptions.resolveDestination.notifier).update,
|
||||
),
|
||||
ChoicePreferenceWidget(
|
||||
selected: ref.watch(ConfigOptions.ipv6Mode),
|
||||
@@ -179,28 +161,24 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SettingsSection(t.config.section.dns),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.remoteDnsAddress),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.remoteDnsAddress.notifier),
|
||||
preferences: ref.watch(ConfigOptions.remoteDnsAddress.notifier),
|
||||
title: t.config.remoteDnsAddress,
|
||||
),
|
||||
ChoicePreferenceWidget(
|
||||
selected: ref.watch(ConfigOptions.remoteDnsDomainStrategy),
|
||||
preferences: ref
|
||||
.watch(ConfigOptions.remoteDnsDomainStrategy.notifier),
|
||||
preferences: ref.watch(ConfigOptions.remoteDnsDomainStrategy.notifier),
|
||||
choices: DomainStrategy.values,
|
||||
title: t.config.remoteDnsDomainStrategy,
|
||||
presentChoice: (value) => value.displayName,
|
||||
),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.directDnsAddress),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.directDnsAddress.notifier),
|
||||
preferences: ref.watch(ConfigOptions.directDnsAddress.notifier),
|
||||
title: t.config.directDnsAddress,
|
||||
),
|
||||
ChoicePreferenceWidget(
|
||||
selected: ref.watch(ConfigOptions.directDnsDomainStrategy),
|
||||
preferences: ref
|
||||
.watch(ConfigOptions.directDnsDomainStrategy.notifier),
|
||||
preferences: ref.watch(ConfigOptions.directDnsDomainStrategy.notifier),
|
||||
choices: DomainStrategy.values,
|
||||
title: t.config.directDnsDomainStrategy,
|
||||
presentChoice: (value) => value.displayName,
|
||||
@@ -208,9 +186,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SwitchListTile(
|
||||
title: Text(t.config.enableDnsRouting),
|
||||
value: ref.watch(ConfigOptions.enableDnsRouting),
|
||||
onChanged: ref
|
||||
.watch(ConfigOptions.enableDnsRouting.notifier)
|
||||
.update,
|
||||
onChanged: ref.watch(ConfigOptions.enableDnsRouting.notifier).update,
|
||||
),
|
||||
// const SettingsDivider(),
|
||||
// SettingsSection(experimental(t.config.section.mux)),
|
||||
@@ -247,13 +223,11 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SwitchListTile(
|
||||
title: Text(t.config.strictRoute),
|
||||
value: ref.watch(ConfigOptions.strictRoute),
|
||||
onChanged:
|
||||
ref.watch(ConfigOptions.strictRoute.notifier).update,
|
||||
onChanged: ref.watch(ConfigOptions.strictRoute.notifier).update,
|
||||
),
|
||||
ChoicePreferenceWidget(
|
||||
selected: ref.watch(ConfigOptions.tunImplementation),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.tunImplementation.notifier),
|
||||
preferences: ref.watch(ConfigOptions.tunImplementation.notifier),
|
||||
choices: TunImplementation.values,
|
||||
title: t.config.tunImplementation,
|
||||
presentChoice: (value) => value.name,
|
||||
@@ -287,25 +261,21 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
experimental(t.config.allowConnectionFromLan),
|
||||
),
|
||||
value: ref.watch(ConfigOptions.allowConnectionFromLan),
|
||||
onChanged: ref
|
||||
.read(ConfigOptions.allowConnectionFromLan.notifier)
|
||||
.update,
|
||||
onChanged: ref.read(ConfigOptions.allowConnectionFromLan.notifier).update,
|
||||
),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(
|
||||
experimental(t.config.section.tlsTricks),
|
||||
key: ConfigOptionSection._fragmentKey,
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.config.enableTlsFragment),
|
||||
value: ref.watch(ConfigOptions.enableTlsFragment),
|
||||
onChanged: ref
|
||||
.watch(ConfigOptions.enableTlsFragment.notifier)
|
||||
.update,
|
||||
onChanged: ref.watch(ConfigOptions.enableTlsFragment.notifier).update,
|
||||
),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.tlsFragmentSize),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.tlsFragmentSize.notifier),
|
||||
preferences: ref.watch(ConfigOptions.tlsFragmentSize.notifier),
|
||||
title: t.config.tlsFragmentSize,
|
||||
inputToValue: OptionalRange.tryParse,
|
||||
presentValue: (value) => value.present(t),
|
||||
@@ -313,8 +283,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.tlsFragmentSleep),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.tlsFragmentSleep.notifier),
|
||||
preferences: ref.watch(ConfigOptions.tlsFragmentSleep.notifier),
|
||||
title: t.config.tlsFragmentSleep,
|
||||
inputToValue: OptionalRange.tryParse,
|
||||
presentValue: (value) => value.present(t),
|
||||
@@ -323,21 +292,16 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SwitchListTile(
|
||||
title: Text(t.config.enableTlsMixedSniCase),
|
||||
value: ref.watch(ConfigOptions.enableTlsMixedSniCase),
|
||||
onChanged: ref
|
||||
.watch(ConfigOptions.enableTlsMixedSniCase.notifier)
|
||||
.update,
|
||||
onChanged: ref.watch(ConfigOptions.enableTlsMixedSniCase.notifier).update,
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.config.enableTlsPadding),
|
||||
value: ref.watch(ConfigOptions.enableTlsPadding),
|
||||
onChanged: ref
|
||||
.watch(ConfigOptions.enableTlsPadding.notifier)
|
||||
.update,
|
||||
onChanged: ref.watch(ConfigOptions.enableTlsPadding.notifier).update,
|
||||
),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.tlsPaddingSize),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.tlsPaddingSize.notifier),
|
||||
preferences: ref.watch(ConfigOptions.tlsPaddingSize.notifier),
|
||||
title: t.config.tlsPaddingSize,
|
||||
inputToValue: OptionalRange.tryParse,
|
||||
presentValue: (value) => value.format(),
|
||||
@@ -350,38 +314,26 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
SettingsSection(t.config.section.misc),
|
||||
ValuePreferenceWidget(
|
||||
value: ref.watch(ConfigOptions.connectionTestUrl),
|
||||
preferences:
|
||||
ref.watch(ConfigOptions.connectionTestUrl.notifier),
|
||||
preferences: ref.watch(ConfigOptions.connectionTestUrl.notifier),
|
||||
title: t.config.connectionTestUrl,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.config.urlTestInterval),
|
||||
subtitle: Text(
|
||||
ref
|
||||
.watch(ConfigOptions.urlTestInterval)
|
||||
.toApproximateTime(isRelativeToNow: false),
|
||||
ref.watch(ConfigOptions.urlTestInterval).toApproximateTime(isRelativeToNow: false),
|
||||
),
|
||||
onTap: () async {
|
||||
final urlTestInterval = await SettingsSliderDialog(
|
||||
title: t.config.urlTestInterval,
|
||||
initialValue: ref
|
||||
.watch(ConfigOptions.urlTestInterval)
|
||||
.inMinutes
|
||||
.coerceIn(0, 60)
|
||||
.toDouble(),
|
||||
onReset: ref
|
||||
.read(ConfigOptions.urlTestInterval.notifier)
|
||||
.reset,
|
||||
initialValue: ref.watch(ConfigOptions.urlTestInterval).inMinutes.coerceIn(0, 60).toDouble(),
|
||||
onReset: ref.read(ConfigOptions.urlTestInterval.notifier).reset,
|
||||
min: 1,
|
||||
max: 60,
|
||||
divisions: 60,
|
||||
labelGen: (value) => Duration(minutes: value.toInt())
|
||||
.toApproximateTime(isRelativeToNow: false),
|
||||
labelGen: (value) => Duration(minutes: value.toInt()).toApproximateTime(isRelativeToNow: false),
|
||||
).show(context);
|
||||
if (urlTestInterval == null) return;
|
||||
await ref
|
||||
.read(ConfigOptions.urlTestInterval.notifier)
|
||||
.update(Duration(minutes: urlTestInterval.toInt()));
|
||||
await ref.read(ConfigOptions.urlTestInterval.notifier).update(Duration(minutes: urlTestInterval.toInt()));
|
||||
},
|
||||
),
|
||||
ValuePreferenceWidget(
|
||||
|
||||
@@ -63,17 +63,15 @@ class WarpOptionsTiles extends HookConsumerWidget {
|
||||
AsyncLoading() => const LinearProgressIndicator(),
|
||||
AsyncError() => Text(
|
||||
t.config.missingWarpConfig,
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
_ => null,
|
||||
}
|
||||
: null,
|
||||
enabled: canChangeOptions,
|
||||
onTap: () async {
|
||||
await ref
|
||||
.read(warpOptionNotifierProvider.notifier)
|
||||
.generateWarpConfig();
|
||||
await ref.read(warpOptionNotifierProvider.notifier).generateWarpConfig();
|
||||
await ref.read(warpOptionNotifierProvider.notifier).generateWarp2Config();
|
||||
},
|
||||
),
|
||||
ChoicePreferenceWidget(
|
||||
@@ -111,8 +109,7 @@ class WarpOptionsTiles extends HookConsumerWidget {
|
||||
preferences: ref.watch(ConfigOptions.warpNoise.notifier),
|
||||
enabled: canChangeOptions,
|
||||
title: t.config.warpNoise,
|
||||
inputToValue: (input) =>
|
||||
OptionalRange.tryParse(input, allowEmpty: true),
|
||||
inputToValue: (input) => OptionalRange.tryParse(input, allowEmpty: true),
|
||||
presentValue: (value) => value.present(t),
|
||||
formatInputValue: (value) => value.format(),
|
||||
),
|
||||
@@ -121,8 +118,7 @@ class WarpOptionsTiles extends HookConsumerWidget {
|
||||
preferences: ref.watch(ConfigOptions.warpNoiseDelay.notifier),
|
||||
enabled: canChangeOptions,
|
||||
title: t.config.warpNoiseDelay,
|
||||
inputToValue: (input) =>
|
||||
OptionalRange.tryParse(input, allowEmpty: true),
|
||||
inputToValue: (input) => OptionalRange.tryParse(input, allowEmpty: true),
|
||||
presentValue: (value) => value.present(t),
|
||||
formatInputValue: (value) => value.format(),
|
||||
),
|
||||
|
||||
@@ -16,8 +16,7 @@ class QuickSettingsModal extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final t = ref.watch(translationsProvider);
|
||||
|
||||
final warpPrefaceCompleted =
|
||||
ref.watch(warpOptionNotifierProvider).consentGiven;
|
||||
final warpPrefaceCompleted = ref.watch(warpOptionNotifierProvider).consentGiven;
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
@@ -33,37 +32,41 @@ class QuickSettingsModal extends HookConsumerWidget {
|
||||
e.presentShort(t),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
tooltip:
|
||||
e.isExperimental ? t.settings.experimental : null,
|
||||
tooltip: e.isExperimental ? t.settings.experimental : null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
selected: {ref.watch(ConfigOptions.serviceMode)},
|
||||
onSelectionChanged: (newSet) => ref
|
||||
.read(ConfigOptions.serviceMode.notifier)
|
||||
.update(newSet.first),
|
||||
onSelectionChanged: (newSet) => ref.read(ConfigOptions.serviceMode.notifier).update(newSet.first),
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
if (warpPrefaceCompleted)
|
||||
SwitchListTile(
|
||||
value: ref.watch(ConfigOptions.enableWarp),
|
||||
onChanged: ref.watch(ConfigOptions.enableWarp.notifier).update,
|
||||
title: Text(t.config.enableWarp),
|
||||
GestureDetector(
|
||||
onLongPress: () {
|
||||
ConfigOptionsRoute(section: ConfigOptionSection.warp.name).go(context);
|
||||
},
|
||||
child: SwitchListTile(
|
||||
value: ref.watch(ConfigOptions.enableWarp),
|
||||
onChanged: ref.watch(ConfigOptions.enableWarp.notifier).update,
|
||||
title: Text(t.config.enableWarp),
|
||||
),
|
||||
)
|
||||
else
|
||||
ListTile(
|
||||
title: Text(t.config.setupWarp),
|
||||
trailing: const Icon(FluentIcons.chevron_right_24_regular),
|
||||
onTap: () =>
|
||||
ConfigOptionsRoute(section: ConfigOptionSection.warp.name)
|
||||
.go(context),
|
||||
onTap: () => ConfigOptionsRoute(section: ConfigOptionSection.warp.name).go(context),
|
||||
),
|
||||
GestureDetector(
|
||||
onLongPress: () {
|
||||
ConfigOptionsRoute(section: ConfigOptionSection.fragment.name).go(context);
|
||||
},
|
||||
child: SwitchListTile(
|
||||
value: ref.watch(ConfigOptions.enableTlsFragment),
|
||||
onChanged: ref.watch(ConfigOptions.enableTlsFragment.notifier).update,
|
||||
title: Text(t.config.enableTlsFragment),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: ref.watch(ConfigOptions.enableTlsFragment),
|
||||
onChanged:
|
||||
ref.watch(ConfigOptions.enableTlsFragment.notifier).update,
|
||||
title: Text(t.config.enableTlsFragment),
|
||||
),
|
||||
// SwitchListTile(
|
||||
// value: ref.watch(ConfigOptions.enableMux),
|
||||
|
||||
Reference in New Issue
Block a user