Add experimental feature notice

This commit is contained in:
problematicconsumer
2023-12-31 10:28:52 +03:30
parent ab06d98306
commit 4f4931309f
8 changed files with 143 additions and 7 deletions

View File

@@ -25,7 +25,10 @@
"tapToConnect": "Tap to Connect", "tapToConnect": "Tap to Connect",
"connecting": "Connecting", "connecting": "Connecting",
"disconnecting": "Disconnecting", "disconnecting": "Disconnecting",
"connected": "Connected" "connected": "Connected",
"experimentalNotice": "Experimental Features In Use",
"experimentalNoticeMsg": "You've enabled some experimental features which might affect connection quality and cause unexpected errors. You can always change or reset these options from Config options page.",
"disableExperimentalNotice": "Don't show again"
}, },
"stats": { "stats": {
"traffic": "Live Traffic", "traffic": "Live Traffic",

View File

@@ -25,7 +25,10 @@
"tapToConnect": "برای اتصال ضربه بزنید", "tapToConnect": "برای اتصال ضربه بزنید",
"connecting": "در حال اتصال", "connecting": "در حال اتصال",
"disconnecting": "در حال قطع اتصال", "disconnecting": "در حال قطع اتصال",
"connected": "متصل" "connected": "متصل",
"experimentalNotice": "اخطار استفاده از ویژگی‌های آزمایشی",
"experimentalNoticeMsg": "برخی از ویژگی‌های آزمایشی را فعال کرده‌اید که ممکن است بر کیفیت اتصال تأثیر بگذارد و باعث خطاهای غیرمنتظره شود. همیشه می‌توانید این گزینه‌ها را از صفحه تنظیمات کانفیگ تغییر دهید یا بازنشانی کنید.",
"disableExperimentalNotice": "دیگر نشان نده"
}, },
"stats": { "stats": {
"traffic": "مصرف لحظه‌ای", "traffic": "مصرف لحظه‌ای",

View File

@@ -25,7 +25,10 @@
"tapToConnect": "Нажмите для подключения", "tapToConnect": "Нажмите для подключения",
"connecting": "Подключение", "connecting": "Подключение",
"disconnecting": "Отключение", "disconnecting": "Отключение",
"connected": "Подключено" "connected": "Подключено",
"experimentalNotice": "Экспериментальные функции в использовании",
"experimentalNoticeMsg": "Вы включили некоторые экспериментальные функции, которые могут повлиять на качество соединения и вызвать непредвиденные ошибки. Вы всегда можете изменить или сбросить эти параметры на странице параметров конфигурации.",
"disableExperimentalNotice": "Больше не показывать"
}, },
"stats": { "stats": {
"traffic": "Текущий трафик", "traffic": "Текущий трафик",

View File

@@ -25,7 +25,10 @@
"tapToConnect": "Bağlanmak için dokunun", "tapToConnect": "Bağlanmak için dokunun",
"connecting": "Bağlanıyor", "connecting": "Bağlanıyor",
"disconnecting": "Bağlantı kesiliyor", "disconnecting": "Bağlantı kesiliyor",
"connected": "Bağlandı" "connected": "Bağlandı",
"experimentalNotice": "Kullanımdaki Deneysel Özellikler",
"experimentalNoticeMsg": "Bağlantı kalitesini etkileyebilecek ve beklenmeyen hatalara neden olabilecek bazı deneysel özellikleri etkinleştirdiniz. Bu seçenekleri istediğiniz zaman Yapılandırma seçenekleri sayfasından değiştirebilir veya sıfırlayabilirsiniz.",
"disableExperimentalNotice": "Bir daha gösterme"
}, },
"stats": { "stats": {
"traffic": "Canlı Trafik", "traffic": "Canlı Trafik",

View File

@@ -25,7 +25,10 @@
"tapToConnect": "点击连接", "tapToConnect": "点击连接",
"connecting": "正在连接", "connecting": "正在连接",
"disconnecting": "正在断开连接", "disconnecting": "正在断开连接",
"connected": "已连接" "connected": "已连接",
"experimentalNotice": "使用中的实验功能",
"experimentalNoticeMsg": "您启用了一些实验性功能,这些功能可能会影响连接质量并导致意外错误。您始终可以从“配置选项”页面更改或重置这些选项。",
"disableExperimentalNotice": "不再显示"
}, },
"stats": { "stats": {
"traffic": "实时流量", "traffic": "实时流量",

View File

@@ -6,6 +6,7 @@ import 'package:hiddify/core/utils/json_converters.dart';
import 'package:hiddify/features/config_option/model/config_option_patch.dart'; import 'package:hiddify/features/config_option/model/config_option_patch.dart';
import 'package:hiddify/features/log/model/log_level.dart'; import 'package:hiddify/features/log/model/log_level.dart';
import 'package:hiddify/singbox/model/singbox_config_enum.dart'; import 'package:hiddify/singbox/model/singbox_config_enum.dart';
import 'package:hiddify/utils/platform_utils.dart';
part 'config_option_entity.freezed.dart'; part 'config_option_entity.freezed.dart';
part 'config_option_entity.g.dart'; part 'config_option_entity.g.dart';
@@ -56,6 +57,17 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
serviceMode: ServiceMode.defaultMode, serviceMode: ServiceMode.defaultMode,
); );
bool hasExperimentalOptions() {
if (PlatformUtils.isDesktop && serviceMode == ServiceMode.tun) {
return true;
}
if (enableTlsFragment || enableTlsMixedSniCase || enableTlsPadding) {
return true;
}
return false;
}
String format() { String format() {
const encoder = JsonEncoder.withIndent(' '); const encoder = JsonEncoder.withIndent(' ');
return encoder.convert(toJson()); return encoder.convert(toJson());

View File

@@ -0,0 +1,85 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/core/preferences/preferences_provider.dart';
import 'package:hiddify/core/router/routes.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'experimental_feature_notice.g.dart';
@riverpod
class DisableExperimentalFeatureNotice
extends _$DisableExperimentalFeatureNotice {
static const _key = "disable_experimental_feature_notice";
@override
bool build() {
return ref.read(sharedPreferencesProvider).requireValue.getBool(_key) ??
false;
}
Future<void> change(bool pref) async {
state = pref;
await ref.read(sharedPreferencesProvider).requireValue.setBool(_key, pref);
}
}
class ExperimentalFeatureNoticeDialog extends HookConsumerWidget {
const ExperimentalFeatureNoticeDialog({super.key});
Future<bool?> show(BuildContext context) async {
return showDialog<bool>(
context: context,
builder: (context) => this,
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final t = ref.watch(translationsProvider);
final shouldDisable =
useState(ref.read(disableExperimentalFeatureNoticeProvider));
return PopScope(
onPopInvoked: (didPop) async {
await ref
.read(disableExperimentalFeatureNoticeProvider.notifier)
.change(shouldDisable.value);
},
child: AlertDialog(
title: Text(t.home.connection.experimentalNotice),
content: SingleChildScrollView(
child: SizedBox(
width: 468,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(t.home.connection.experimentalNoticeMsg),
CheckboxListTile(
value: shouldDisable.value,
title: Text(t.home.connection.disableExperimentalNotice),
onChanged: (value) => shouldDisable.value = value ?? false,
),
],
),
),
),
actions: [
TextButton(
onPressed: () async {
await Navigator.of(context).maybePop(false);
if (context.mounted) const ConfigOptionsRoute().push(context);
},
child: Text(t.settings.config.pageTitle),
),
TextButton(
onPressed: () => Navigator.of(context).maybePop(true),
child: Text(MaterialLocalizations.of(context).okButtonLabel),
),
],
),
);
}
}

View File

@@ -4,8 +4,10 @@ import 'package:gap/gap.dart';
import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/core/model/failures.dart'; import 'package:hiddify/core/model/failures.dart';
import 'package:hiddify/core/theme/theme_extensions.dart'; import 'package:hiddify/core/theme/theme_extensions.dart';
import 'package:hiddify/features/config_option/notifier/config_option_notifier.dart';
import 'package:hiddify/features/connection/model/connection_status.dart'; import 'package:hiddify/features/connection/model/connection_status.dart';
import 'package:hiddify/features/connection/notifier/connection_notifier.dart'; import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
import 'package:hiddify/features/connection/widget/experimental_feature_notice.dart';
import 'package:hiddify/gen/assets.gen.dart'; import 'package:hiddify/gen/assets.gen.dart';
import 'package:hiddify/utils/alerts.dart'; import 'package:hiddify/utils/alerts.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -42,8 +44,30 @@ class ConnectionButton extends HookConsumerWidget {
: buttonTheme.idleColor!; : buttonTheme.idleColor!;
return _ConnectionButton( return _ConnectionButton(
onTap: () => onTap: () async {
ref.read(connectionNotifierProvider.notifier).toggleConnection(), var canConnect = true;
if (status case Disconnected()) {
final hasExperimental =
await ref.read(configOptionNotifierProvider.future).then(
(value) => value.hasExperimentalOptions(),
onError: (_) => false,
);
final canShowNotice =
!ref.read(disableExperimentalFeatureNoticeProvider);
if (hasExperimental && canShowNotice && context.mounted) {
canConnect = await const ExperimentalFeatureNoticeDialog()
.show(context) ??
true;
}
}
if (canConnect) {
await ref
.read(connectionNotifierProvider.notifier)
.toggleConnection();
}
},
enabled: !status.isSwitching, enabled: !status.isSwitching,
label: status.present(t), label: status.present(t),
buttonColor: connectionLogoColor, buttonColor: connectionLogoColor,