Fix text input traversal
This commit is contained in:
@@ -45,55 +45,74 @@ class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
|
|||||||
text: initialValue?.toString(),
|
text: initialValue?.toString(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return AlertDialog(
|
return FocusTraversalGroup(
|
||||||
title: Text(title),
|
policy: OrderedTraversalPolicy(),
|
||||||
icon: icon != null ? Icon(icon) : null,
|
child: AlertDialog(
|
||||||
content: TextFormField(
|
title: Text(title),
|
||||||
controller: textController,
|
icon: icon != null ? Icon(icon) : null,
|
||||||
inputFormatters: [
|
content: FocusTraversalOrder(
|
||||||
FilteringTextInputFormatter.singleLineFormatter,
|
order: const NumericFocusOrder(1),
|
||||||
if (digitsOnly) FilteringTextInputFormatter.digitsOnly,
|
child: CustomTextFormField(
|
||||||
|
controller: textController,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.singleLineFormatter,
|
||||||
|
if (digitsOnly) FilteringTextInputFormatter.digitsOnly,
|
||||||
|
],
|
||||||
|
autoCorrect: true,
|
||||||
|
hint: title,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
if (optionalAction != null)
|
||||||
|
FocusTraversalOrder(
|
||||||
|
order: const NumericFocusOrder(5),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
optionalAction!.$2();
|
||||||
|
await Navigator.of(context)
|
||||||
|
.maybePop(T == String ? textController.value.text : null);
|
||||||
|
},
|
||||||
|
child: Text(optionalAction!.$1.toUpperCase()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (resetValue != null)
|
||||||
|
FocusTraversalOrder(
|
||||||
|
order: const NumericFocusOrder(4),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Navigator.of(context).maybePop(resetValue);
|
||||||
|
},
|
||||||
|
child: Text(t.general.reset.toUpperCase()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FocusTraversalOrder(
|
||||||
|
order: const NumericFocusOrder(3),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
|
},
|
||||||
|
child: Text(localizations.cancelButtonLabel.toUpperCase()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FocusTraversalOrder(
|
||||||
|
order: const NumericFocusOrder(2),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
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));
|
||||||
|
} else {
|
||||||
|
await Navigator.of(context)
|
||||||
|
.maybePop(T == String ? textController.value.text : null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(localizations.okButtonLabel.toUpperCase()),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
autovalidateMode: AutovalidateMode.always,
|
|
||||||
),
|
),
|
||||||
actions: [
|
|
||||||
if (optionalAction != null)
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
optionalAction!.$2();
|
|
||||||
await Navigator.of(context)
|
|
||||||
.maybePop(T == String ? textController.value.text : null);
|
|
||||||
},
|
|
||||||
child: Text(optionalAction!.$1.toUpperCase()),
|
|
||||||
),
|
|
||||||
if (resetValue != null)
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await Navigator.of(context).maybePop(resetValue);
|
|
||||||
},
|
|
||||||
child: Text(t.general.reset.toUpperCase()),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await Navigator.of(context).maybePop();
|
|
||||||
},
|
|
||||||
child: Text(localizations.cancelButtonLabel.toUpperCase()),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
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));
|
|
||||||
} else {
|
|
||||||
await Navigator.of(context)
|
|
||||||
.maybePop(T == String ? textController.value.text : null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(localizations.okButtonLabel.toUpperCase()),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hiddify/utils/text_utils.dart';
|
import 'package:hiddify/utils/text_utils.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -6,9 +7,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
class CustomTextFormField extends HookConsumerWidget {
|
class CustomTextFormField extends HookConsumerWidget {
|
||||||
const CustomTextFormField({
|
const CustomTextFormField({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onChanged,
|
this.onChanged,
|
||||||
this.validator,
|
this.validator,
|
||||||
this.controller,
|
this.controller,
|
||||||
|
this.inputFormatters,
|
||||||
this.initialValue = '',
|
this.initialValue = '',
|
||||||
this.suffixIcon,
|
this.suffixIcon,
|
||||||
this.label,
|
this.label,
|
||||||
@@ -19,9 +21,10 @@ class CustomTextFormField extends HookConsumerWidget {
|
|||||||
this.autoCorrect = false,
|
this.autoCorrect = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
final String? Function(String? value)? validator;
|
final String? Function(String? value)? validator;
|
||||||
final TextEditingController? controller;
|
final TextEditingController? controller;
|
||||||
|
final List<TextInputFormatter>? inputFormatters;
|
||||||
final String initialValue;
|
final String initialValue;
|
||||||
final Widget? suffixIcon;
|
final Widget? suffixIcon;
|
||||||
final String? label;
|
final String? label;
|
||||||
@@ -51,6 +54,8 @@ class CustomTextFormField extends HookConsumerWidget {
|
|||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
textDirection: textController.textDirection,
|
textDirection: textController.textDirection,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
|
textInputAction: TextInputAction.next,
|
||||||
|
inputFormatters: inputFormatters,
|
||||||
autovalidateMode:
|
autovalidateMode:
|
||||||
autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,
|
autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,
|
||||||
autocorrect: autoCorrect,
|
autocorrect: autoCorrect,
|
||||||
|
|||||||
Reference in New Issue
Block a user