Skip to content

Commit

Permalink
new: add several values for dns and url test in auto complete mode
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddify-com committed Aug 20, 2024
1 parent 4726c8a commit 66353a6
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 49 deletions.
35 changes: 15 additions & 20 deletions lib/core/utils/preferences_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,35 +96,30 @@ class PreferencesNotifier<T, P> extends StateNotifier<T> {
required Ref ref,
required this.entry,
this.overrideValue,
this.possibleValues,
}) : _ref = ref,
super(overrideValue ?? entry.read());

final Ref _ref;
final PreferencesEntry<T, P> entry;
final T? overrideValue;
final List<T>? possibleValues;

static StateNotifierProvider<PreferencesNotifier<T, P>, T> create<T, P>(
String key,
T defaultValue, {
T Function(Ref ref)? defaultValueFunction,
T Function(P value)? mapFrom,
P Function(T value)? mapTo,
bool Function(T value)? validator,
T? overrideValue,
}) =>
static StateNotifierProvider<PreferencesNotifier<T, P>, T> create<T, P>(String key, T defaultValue,
{T Function(Ref ref)? defaultValueFunction, T Function(P value)? mapFrom, P Function(T value)? mapTo, bool Function(T value)? validator, T? overrideValue, List<T>? possibleValues}) =>
StateNotifierProvider(
(ref) => PreferencesNotifier._(
ref: ref,
entry: PreferencesEntry<T, P>(
preferences: ref.read(sharedPreferencesProvider).requireValue,
key: key,
defaultValue: defaultValueFunction?.call(ref) ?? defaultValue,
mapFrom: mapFrom,
mapTo: mapTo,
validator: validator,
),
overrideValue: overrideValue,
),
ref: ref,
entry: PreferencesEntry<T, P>(
preferences: ref.read(sharedPreferencesProvider).requireValue,
key: key,
defaultValue: defaultValueFunction?.call(ref) ?? defaultValue,
mapFrom: mapFrom,
mapTo: mapTo,
validator: validator,
),
overrideValue: overrideValue,
possibleValues: possibleValues),
);

static AutoDisposeStateNotifierProvider<PreferencesNotifier<T, P>, T> createAutoDispose<T, P>(
Expand Down
38 changes: 35 additions & 3 deletions lib/features/config_option/data/config_option_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ abstract class ConfigOptions {
static final remoteDnsAddress = PreferencesNotifier.create<String, String>(
"remote-dns-address",
"udp://1.1.1.1",
// "https://sky.rethinkdns.com/dns-query",
possibleValues: List.of([
"local",
"udp://223.5.5.5",
"udp://1.1.1.1",
"udp://1.1.1.2",
"tcp://1.1.1.1",
"https://1.1.1.1/dns-query",
"https://sky.rethinkdns.com/dns-query",
"4.4.2.2",
"8.8.8.8",
]),
validator: (value) => value.isNotBlank,
);

Expand All @@ -74,7 +84,18 @@ abstract class ConfigOptions {

static final directDnsAddress = PreferencesNotifier.create<String, String>(
"direct-dns-address",
"1.1.1.1",
"udp://1.1.1.1",
possibleValues: List.of([
"local",
"udp://223.5.5.5",
"udp://1.1.1.1",
"udp://1.1.1.2",
"tcp://1.1.1.1",
"https://1.1.1.1/dns-query",
"https://sky.rethinkdns.com/dns-query",
"4.4.2.2",
"8.8.8.8",
]),
defaultValueFunction: (ref) => ref.read(region) == Region.cn ? "223.5.5.5" : "1.1.1.1",
validator: (value) => value.isNotBlank,
);
Expand Down Expand Up @@ -117,7 +138,18 @@ abstract class ConfigOptions {

static final connectionTestUrl = PreferencesNotifier.create<String, String>(
"connection-test-url",
"http://connectivitycheck.gstatic.com/generate_204",
"http://cp.cloudflare.com",
possibleValues: List.of([
"http://connectivitycheck.gstatic.com/generate_204",
"http://www.gstatic.com/generate_204",
"https://www.gstatic.com/generate_204",
"http://cp.cloudflare.com",
"http://kernel.org",
"http://detectportal.firefox.com",
"http://captive.apple.com/hotspot-detect.html",
"https://1.1.1.1",
"http://1.1.1.1",
]),
validator: (value) => value.isNotBlank && isUrl(value),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
digitsOnly: true,
inputToValue: int.tryParse,
),

SwitchListTile(
title: Text(experimental(t.config.useXrayCoreWhenPossible.Label)),
subtitle: Text(t.config.useXrayCoreWhenPossible.Description),
Expand Down
1 change: 1 addition & 0 deletions lib/features/config_option/widget/preference_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ValuePreferenceWidget<T> extends StatelessWidget {
onReset: preferences.reset,
digitsOnly: digitsOnly,
mapTo: inputToValue,
possibleValues: preferences.possibleValues,
).show(context);
if (inputValue == null) {
return;
Expand Down
72 changes: 47 additions & 25 deletions lib/features/settings/widgets/settings_input_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/utils/utils.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
const SettingsInputDialog({
super.key,
required this.title,
required this.initialValue,
this.mapTo,
this.validator,
this.valueFormatter,
this.onReset,
this.optionalAction,
this.icon,
this.digitsOnly = false,
});
const SettingsInputDialog({super.key, required this.title, required this.initialValue, this.mapTo, this.validator, this.valueFormatter, this.onReset, this.optionalAction, this.icon, this.digitsOnly = false, this.possibleValues});

final String title;
final T initialValue;
final T? Function(String value)? mapTo;
final bool Function(String value)? validator;
final String Function(T value)? valueFormatter;
final List<T>? possibleValues;
final VoidCallback? onReset;
final (String text, VoidCallback)? optionalAction;
final IconData? icon;
Expand Down Expand Up @@ -53,14 +44,22 @@ class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
icon: icon != null ? Icon(icon) : null,
content: FocusTraversalOrder(
order: const NumericFocusOrder(1),
child: CustomTextFormField(
controller: textController,
inputFormatters: [
FilteringTextInputFormatter.singleLineFormatter,
if (digitsOnly) FilteringTextInputFormatter.digitsOnly,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (possibleValues != null)
AutocompleteField(initialValue: initialValue.toString(), options: possibleValues!.map((e) => e.toString()).toList())
else
CustomTextFormField(
controller: textController,
inputFormatters: [
FilteringTextInputFormatter.singleLineFormatter,
if (digitsOnly) FilteringTextInputFormatter.digitsOnly,
],
autoCorrect: true,
hint: title,
),
],
autoCorrect: true,
hint: title,
),
),
actions: [
Expand All @@ -70,8 +69,7 @@ class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
child: TextButton(
onPressed: () async {
optionalAction!.$2();
await Navigator.of(context)
.maybePop(T == String ? textController.value.text : null);
await Navigator.of(context).maybePop(T == String ? textController.value.text : null);
},
child: Text(optionalAction!.$1.toUpperCase()),
),
Expand Down Expand Up @@ -103,11 +101,9 @@ class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
if (validator?.call(textController.value.text) == false) {
await Navigator.of(context).maybePop(null);
} else if (mapTo != null) {
await Navigator.of(context)
.maybePop(mapTo!.call(textController.value.text));
await Navigator.of(context).maybePop(mapTo!.call(textController.value.text));
} else {
await Navigator.of(context)
.maybePop(T == String ? textController.value.text : null);
await Navigator.of(context).maybePop(T == String ? textController.value.text : null);
}
},
child: Text(localizations.okButtonLabel.toUpperCase()),
Expand All @@ -119,6 +115,32 @@ class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
}
}

class AutocompleteField extends StatelessWidget {
const AutocompleteField({super.key, required this.initialValue, required this.options});
final List<String> options;
final String initialValue;

@override
Widget build(BuildContext context) {
return Autocomplete<String>(
initialValue: TextEditingValue(
text: this.initialValue, selection: TextSelection(baseOffset: 0, extentOffset: this.initialValue.length), // Selects the entire text
),
optionsBuilder: (TextEditingValue textEditingValue) {
// if (textEditingValue.text == '') {
// return const Iterable<String>.empty();
// }
return options.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
onSelected: (String selection) {
//debugPrint('You just selected $selection');
},
);
}
}

class SettingsPickerDialog<T> extends HookConsumerWidget with PresLogger {
const SettingsPickerDialog({
super.key,
Expand Down

2 comments on commit 66353a6

@hosseinfarnia
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

اگه ممکنه این هم به remote dns اضافه کنید:
https://8.8.8.8/dns-query
برای دایرکت
direct: 8.8.8.8

@hosseinfarnia
Copy link

@hosseinfarnia hosseinfarnia commented on 66353a6 Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

چهارتا ۱ و چهارتا ۸ خالی در remote dns با سابهای پنل bpb کار نمیکنه
سازندش گفته کاریش نمیشه کرد
باید از سمت کلاینت تغییرش بدید

Please sign in to comment.