diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7fd17e2..4fe20b3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -710,5 +710,8 @@ "fallbackDnsServers": "Fallback DNS servers", "fallbackDnsServersDescription": "Configure fallback DNS servers", "fallbackDnsServersInfo": "List of fallback DNS servers used when upstream DNS servers are not responding. The syntax is the same as in the main upstreams field above.", - "noFallbackDnsAdded": "No fallback DNS servers added." + "noFallbackDnsAdded": "No fallback DNS servers added.", + "blockedResponseTtl": "Blocked response TTL", + "blockedResponseTtlDescription": "Specifies for how many seconds the clients should cache a filtered response", + "invalidValue": "Invalid value" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 33b69b1..d3e0855 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -710,5 +710,8 @@ "fallbackDnsServers": "Servidores DNS alternativos", "fallbackDnsServersDescription": "Configura los servidores DNS alternativos", "fallbackDnsServersInfo": "Lista de servidores DNS alternativos utilizados cuando los servidores DNS de subida no responden. La sintaxis es la misma que en el campo de los principales DNS de subida anterior.", - "noFallbackDnsAdded": "No hay servidores DNS alternativos añadidos." + "noFallbackDnsAdded": "No hay servidores DNS alternativos añadidos.", + "blockedResponseTtl": "Respuesta TTL bloqueada", + "blockedResponseTtlDescription": "Especifica durante cuántos segundos los clientes deben almacenar en cache una respuesta filtrada", + "invalidValue": "Valor no válido" } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 20338d3..c0cabd6 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -22,6 +22,7 @@ class DnsInfo { String blockingIpv4; String blockingIpv6; List defaultLocalPtrUpstreams; + int? blockedResponseTtl; DnsInfo({ required this.upstreamDns, @@ -47,6 +48,7 @@ class DnsInfo { required this.blockingIpv4, required this.blockingIpv6, required this.defaultLocalPtrUpstreams, + required this.blockedResponseTtl, }); factory DnsInfo.fromJson(Map json) => DnsInfo( @@ -73,6 +75,7 @@ class DnsInfo { blockingIpv4: json["blocking_ipv4"], blockingIpv6: json["blocking_ipv6"], defaultLocalPtrUpstreams: json["default_local_ptr_upstreams"] != null ? List.from(json["default_local_ptr_upstreams"].map((x) => x)) : [], + blockedResponseTtl: json["blocked_response_ttl"] ); Map toJson() => { @@ -99,5 +102,6 @@ class DnsInfo { "blocking_ipv4": blockingIpv4, "blocking_ipv6": blockingIpv6, "default_local_ptr_upstreams": List.from(defaultLocalPtrUpstreams.map((x) => x)), + "blocked_response_ttl": blockedResponseTtl }; } diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 5a91dfc..c5809af 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -161,6 +161,7 @@ class DnsProvider with ChangeNotifier { data.blockingMode = value['blocking_mode']; data.blockingIpv4 = value['blocking_ipv4']; data.blockingIpv6 = value['blocking_ipv6']; + data.blockedResponseTtl = value['blocked_response_ttl']; setDnsInfoData(data); return result; } diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index 19f6c09..ba04422 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -41,6 +41,9 @@ class _DnsServerSettingsScreenState extends State { final TextEditingController ipv6controller = TextEditingController(); String? ipv6error; + final _ttlController = TextEditingController(); + String? _ttlError; + bool isDataValid = false; void validateIpv4(String value) { @@ -90,7 +93,8 @@ class _DnsServerSettingsScreenState extends State { ipv6error == null ) ) == true && - ednsIpError == null + ednsIpError == null && + _ttlError == null ) { setState(() => isDataValid = true); } @@ -99,6 +103,17 @@ class _DnsServerSettingsScreenState extends State { } } + void validateNumber(String value) { + final regex = RegExp(r'^(\d)+$'); + if (regex.hasMatch(value) == true) { + setState(() => _ttlError = null); + } + else { + setState(() => _ttlError = AppLocalizations.of(context)!.invalidValue); + } + validateData(); + } + @override void initState() { final dnsProvider = Provider.of(context, listen: false); @@ -115,6 +130,9 @@ class _DnsServerSettingsScreenState extends State { ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4; ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6; isDataValid = true; + _ttlController.text = dnsProvider.dnsInfo!.blockedResponseTtl != null + ? dnsProvider.dnsInfo!.blockedResponseTtl.toString() + : ""; super.initState(); } @@ -137,7 +155,8 @@ class _DnsServerSettingsScreenState extends State { "disable_ipv6": disableIpv6Resolving, "blocking_mode": blockingMode, "blocking_ipv4": ipv4controller.text, - "blocking_ipv6": ipv6controller.text + "blocking_ipv6": ipv6controller.text, + "blocked_response_ttl": int.parse(_ttlController.text) }); processModal.close(); @@ -392,8 +411,28 @@ class _DnsServerSettingsScreenState extends State { keyboardType: TextInputType.number, ), ), - const SizedBox(height: 30) - ] + const SizedBox(height: 30), + ], + Padding( + padding: const EdgeInsets.all(16), + child: TextFormField( + controller: _ttlController, + onChanged: validateNumber, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: _ttlError, + labelText: AppLocalizations.of(context)!.blockedResponseTtl, + helperText: AppLocalizations.of(context)!.blockedResponseTtlDescription, + helperMaxLines: 2, + ), + keyboardType: TextInputType.number, + ), + ), ], ), ),