150 lines
6.2 KiB
Dart
150 lines
6.2 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
import 'package:hiddify/core/localization/translations.dart';
|
||
|
|
import 'package:hiddify/core/model/optional_range.dart';
|
||
|
|
import 'package:hiddify/features/config_option/data/config_option_repository.dart';
|
||
|
|
import 'package:hiddify/features/config_option/overview/warp_options_widgets.dart';
|
||
|
|
import 'package:hiddify/features/config_option/widget/preference_tile.dart';
|
||
|
|
import 'package:hiddify/features/settings/widgets/sections_widgets.dart';
|
||
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||
|
|
|
||
|
|
class ExperimentalFeaturesPage extends HookConsumerWidget {
|
||
|
|
const ExperimentalFeaturesPage({super.key});
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
||
|
|
final t = ref.watch(translationsProvider);
|
||
|
|
|
||
|
|
return Scaffold(
|
||
|
|
body: CustomScrollView(
|
||
|
|
slivers: [
|
||
|
|
SliverAppBar.large(
|
||
|
|
title: Text(
|
||
|
|
t.settings.experimental,
|
||
|
|
style: const TextStyle(fontSize: 20),
|
||
|
|
),
|
||
|
|
leading: IconButton(
|
||
|
|
icon: const Icon(Icons.arrow_back),
|
||
|
|
onPressed: () => Navigator.of(context).pop(),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
SliverToBoxAdapter(
|
||
|
|
child: Container(
|
||
|
|
margin: const EdgeInsets.all(16),
|
||
|
|
padding: const EdgeInsets.all(16),
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
color: Theme.of(context).colorScheme.errorContainer.withOpacity(0.3),
|
||
|
|
borderRadius: BorderRadius.circular(12),
|
||
|
|
border: Border.all(
|
||
|
|
color: Theme.of(context).colorScheme.error.withOpacity(0.3),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
child: Row(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Icon(
|
||
|
|
Icons.warning_amber_rounded,
|
||
|
|
color: Theme.of(context).colorScheme.error,
|
||
|
|
size: 24,
|
||
|
|
),
|
||
|
|
const SizedBox(width: 12),
|
||
|
|
Expanded(
|
||
|
|
child: Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Text(
|
||
|
|
t.config.bypassLanWarning.title,
|
||
|
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||
|
|
fontWeight: FontWeight.bold,
|
||
|
|
color: Theme.of(context).colorScheme.error,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
const SizedBox(height: 4),
|
||
|
|
Text(
|
||
|
|
t.settings.experimentalMsg,
|
||
|
|
style: Theme.of(context).textTheme.bodySmall,
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
SliverList.list(
|
||
|
|
children: [
|
||
|
|
// Разрешить подключения из LAN
|
||
|
|
const SettingsDivider(),
|
||
|
|
SettingsSection(t.config.section.route),
|
||
|
|
SwitchListTile(
|
||
|
|
title: Text(t.config.allowConnectionFromLan),
|
||
|
|
value: ref.watch(ConfigOptions.allowConnectionFromLan),
|
||
|
|
onChanged: ref.watch(ConfigOptions.allowConnectionFromLan.notifier).update,
|
||
|
|
),
|
||
|
|
|
||
|
|
// TLS Tricks
|
||
|
|
const SettingsDivider(),
|
||
|
|
SettingsSection(t.config.section.tlsTricks),
|
||
|
|
SwitchListTile(
|
||
|
|
title: Text(t.config.enableTlsFragment),
|
||
|
|
value: ref.watch(ConfigOptions.enableTlsFragment),
|
||
|
|
onChanged: ref.watch(ConfigOptions.enableTlsFragment.notifier).update,
|
||
|
|
),
|
||
|
|
ValuePreferenceWidget(
|
||
|
|
value: ref.watch(ConfigOptions.tlsFragmentSize),
|
||
|
|
preferences: ref.watch(ConfigOptions.tlsFragmentSize.notifier),
|
||
|
|
title: t.config.tlsFragmentSize,
|
||
|
|
inputToValue: OptionalRange.tryParse,
|
||
|
|
presentValue: (value) => value.present(t),
|
||
|
|
formatInputValue: (value) => value.format(),
|
||
|
|
),
|
||
|
|
ValuePreferenceWidget(
|
||
|
|
value: ref.watch(ConfigOptions.tlsFragmentSleep),
|
||
|
|
preferences: ref.watch(ConfigOptions.tlsFragmentSleep.notifier),
|
||
|
|
title: t.config.tlsFragmentSleep,
|
||
|
|
inputToValue: OptionalRange.tryParse,
|
||
|
|
presentValue: (value) => value.present(t),
|
||
|
|
formatInputValue: (value) => value.format(),
|
||
|
|
),
|
||
|
|
SwitchListTile(
|
||
|
|
title: Text(t.config.enableTlsMixedSniCase),
|
||
|
|
value: ref.watch(ConfigOptions.enableTlsMixedSniCase),
|
||
|
|
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,
|
||
|
|
),
|
||
|
|
ValuePreferenceWidget(
|
||
|
|
value: ref.watch(ConfigOptions.tlsPaddingSize),
|
||
|
|
preferences: ref.watch(ConfigOptions.tlsPaddingSize.notifier),
|
||
|
|
title: t.config.tlsPaddingSize,
|
||
|
|
inputToValue: OptionalRange.tryParse,
|
||
|
|
presentValue: (value) => value.format(),
|
||
|
|
formatInputValue: (value) => value.format(),
|
||
|
|
),
|
||
|
|
|
||
|
|
// WARP
|
||
|
|
const SettingsDivider(),
|
||
|
|
SettingsSection(t.config.section.warp),
|
||
|
|
const WarpOptionsTiles(),
|
||
|
|
|
||
|
|
// Использовать Xray Core
|
||
|
|
const SettingsDivider(),
|
||
|
|
SettingsSection(t.config.section.misc),
|
||
|
|
SwitchListTile(
|
||
|
|
title: Text(t.config.useXrayCoreWhenPossible.Label),
|
||
|
|
subtitle: Text(t.config.useXrayCoreWhenPossible.Description),
|
||
|
|
value: ref.watch(ConfigOptions.useXrayCoreWhenPossible),
|
||
|
|
onChanged: ref.watch(ConfigOptions.useXrayCoreWhenPossible.notifier).update,
|
||
|
|
),
|
||
|
|
|
||
|
|
const SizedBox(height: 24),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|