Added server address validation, success message, localization

This commit is contained in:
Anton Stubenbord
2022-12-31 01:35:26 +01:00
parent 2326c9d1d6
commit f390aa6c6a
15 changed files with 315 additions and 151 deletions

View File

@@ -17,26 +17,49 @@ class ServerAddressFormField extends StatefulWidget {
}
class _ServerAddressFormFieldState extends State<ServerAddressFormField> {
static const _ipv4Regex = r"((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}";
static const _ipv6Regex =
r"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
static final _urlRegex = RegExp(
r"^(https?:\/\/)(([\da-z\.-]+)\.([a-z\.]{2,6})|(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})|((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))))(:\d{1,5})?([\/\w \.-]*)*\/?$");
final TextEditingController _textEditingController = TextEditingController();
ReachabilityStatus _reachabilityStatus = ReachabilityStatus.undefined;
@override
Widget build(BuildContext context) {
return FormBuilderTextField(
key: const ValueKey('login-server-address'),
controller: _textEditingController,
name: ServerAddressFormField.fkServerAddress,
validator: FormBuilderValidators.required(
errorText: S.of(context).loginPageServerUrlValidatorMessageText,
validator: FormBuilderValidators.compose(
[
FormBuilderValidators.required(
errorText:
S.of(context).loginPageServerUrlValidatorMessageRequiredText,
),
FormBuilderValidators.match(
_urlRegex.pattern,
errorText: S
.of(context)
.loginPageServerUrlValidatorMessageInvalidAddressText,
),
],
),
inputFormatters: [
FilteringTextInputFormatter.deny(r".*/$"),
FilteringTextInputFormatter.deny(r"\s"),
],
decoration: InputDecoration(
suffixIcon: _buildIsReachableIcon(),
hintText: "http://192.168.1.50:8000",
labelText: S.of(context).loginPageServerUrlFieldLabel,
),
onChanged: _updateIsAddressReachableStatus,
onSubmitted: (value) {
if (value == null) return;
// Remove trailing slash if it is a valid address.
final address = value.trim();
_textEditingController.text = address;
if (_urlRegex.hasMatch(address) && address.endsWith("/")) {
_textEditingController.text = address.replaceAll(RegExp(r'\/$'), '');
}
},
);
}
@@ -60,7 +83,7 @@ class _ServerAddressFormFieldState extends State<ServerAddressFormField> {
}
void _updateIsAddressReachableStatus(String? address) async {
if (address == null || address.isEmpty) {
if (address == null || !_urlRegex.hasMatch(address)) {
setState(() {
_reachabilityStatus = ReachabilityStatus.undefined;
});
@@ -70,12 +93,12 @@ class _ServerAddressFormFieldState extends State<ServerAddressFormField> {
setState(() => _reachabilityStatus = ReachabilityStatus.testing);
final isReachable = await context
.read<ConnectivityStatusService>()
.isServerReachable(address);
if (isReachable) {
setState(() => _reachabilityStatus = ReachabilityStatus.reachable);
} else {
setState(() => _reachabilityStatus = ReachabilityStatus.notReachable);
}
.isServerReachable(address.trim());
setState(
() => _reachabilityStatus = isReachable
? ReachabilityStatus.reachable
: ReachabilityStatus.notReachable,
);
}
}