Added dns settings screen

This commit is contained in:
Juan Gilsanz Polo 2022-10-19 14:12:53 +02:00
parent f74ca8358a
commit e284e95c23
7 changed files with 386 additions and 12 deletions

View file

@ -411,5 +411,18 @@
"logsNotCleared": "Logs could not be cleared",
"runningHomeAssistant": "Running on Home Assistant",
"serverError": "Server error",
"noItems": "No items to show here"
"noItems": "No items to show here",
"dnsSettings": "DNS settings",
"dnsSettingsDescription": "Configure connection with DNS servers",
"upstreamDns": "Upstream DNS servers",
"bootstrapDns": "Bootstrap DNS servers",
"noUpstreamDns": "No upstream DNS servers added.",
"dnsMode": "DNS mode",
"noDnsMode": "No DNS mode selected",
"loadBalancing": "Load balancing",
"parallelRequests": "Parallel requests",
"fastestIpAddress": "Fastest IP address",
"loadBalancingDescription": "Query one upstream server at a time. AdGuard Home uses its weighted random algorithm to pick the server so that the fastest server is used more often.",
"parallelRequestsDescription": "Use parallel queries to speed up resolving by querying all upstream servers simultaneously.",
"fastestIpAddressDescription": "Query all DNS servers and return the fastest IP address among all responses. This slows down DNS queries as AdGuard Home has to wait for responses from all DNS servers, but improves the overall connectivity."
}

View file

@ -411,5 +411,18 @@
"logsNotCleared": "No se han podido borrar los registros",
"runningHomeAssistant": "Ejecutando en Home Assistant",
"serverError": "Error del servidor",
"noItems": "No hay elementos para mostrar aquí"
"noItems": "No hay elementos para mostrar aquí",
"dnsSettings": "Configuración de DNS",
"dnsSettingsDescription": "Configurar conexión con servidores DNS",
"upstreamDns": "Servidores DNS de subida",
"bootstrapDns": "Servidores DNS de arranque",
"noUpstreamDns": "No hay servidores DNS de subida añadidos.",
"dnsMode": "Modo DNS",
"noDnsMode": "No se ha seleccionado modo DNS",
"loadBalancing": "Balanceo de carga",
"parallelRequests": "Peticiones paralelas",
"fastestIpAddress": "Dirección IP más rápida",
"loadBalancingDescription": "Consulta un servidor DNS de subida a la vez. AdGuard Home utiliza su algoritmo aleatorio ponderado para elegir el servidor más rápido y sea utilizado con más frecuencia.",
"parallelRequestsDescription": "Usar consultas paralelas para acelerar la resolución al consultar simultáneamente a todos los servidores DNS de subida.",
"fastestIpAddressDescription": "Consulta todos los servidores DNS y devuelve la dirección IP más rápida de todas las respuestas. Esto ralentiza las consultas DNS ya que AdGuard Home tiene que esperar las respuestas de todos los servidores DNS, pero mejora la conectividad general."
}

View file

@ -0,0 +1,149 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/settings/section_label.dart';
import 'package:adguard_home_manager/screens/settings/dns/dns_mode_modal.dart';
class DnsSettings extends StatefulWidget {
const DnsSettings({Key? key}) : super(key: key);
@override
State<DnsSettings> createState() => _DnsSettingsState();
}
class _DnsSettingsState extends State<DnsSettings> {
List<TextEditingController> upstreamControllers = [
TextEditingController()
];
String upstreamMode = "load_balancing";
@override
Widget build(BuildContext context) {
void openDnsModalSheet() {
showModalBottomSheet(
context: context,
builder: (context) => DnsModeModal(
upstreamMode: upstreamMode,
onConfirm: (value) => setState(() => upstreamMode = value),
),
isScrollControlled: true,
backgroundColor: Colors.transparent
);
}
String getStringUpstreamMode() {
switch (upstreamMode) {
case 'load_balancing':
return AppLocalizations.of(context)!.loadBalancing;
case 'parallel_requests':
return AppLocalizations.of(context)!.parallelRequests;
case 'fastest_ip_address':
return AppLocalizations.of(context)!.fastestIpAddress;
default:
return AppLocalizations.of(context)!.noDnsMode;
}
}
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.dnsSettings),
),
body: ListView(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SectionLabel(label: AppLocalizations.of(context)!.upstreamDns),
Padding(
padding: const EdgeInsets.only(right: 10),
child: IconButton(
onPressed: () => setState(() => upstreamControllers.add(TextEditingController())),
icon: const Icon(Icons.add)
),
)
],
),
if (upstreamControllers.isEmpty) Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Center(
child: Text(
AppLocalizations.of(context)!.noUpstreamDns,
style: const TextStyle(
color: Colors.grey,
fontSize: 16
),
),
),
),
const SizedBox(height: 20),
],
),
...upstreamControllers.map((c) => Padding(
padding: const EdgeInsets.only(
left: 24, right: 10, bottom: 20
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: MediaQuery.of(context).size.width-90,
child: TextFormField(
controller: c,
// onChanged: (_) => checkValidValues(),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.dns_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
labelText: AppLocalizations.of(context)!.dnsServer,
)
),
),
IconButton(
onPressed: () => setState(() => upstreamControllers = upstreamControllers.where((con) => con != c).toList()),
icon: const Icon(Icons.remove_circle_outline)
)
],
),
)).toList(),
Material(
color: Colors.transparent,
child: InkWell(
onTap: openDnsModalSheet,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.dnsMode,
style: const TextStyle(
fontSize: 16,
),
),
const SizedBox(height: 5),
Text(
getStringUpstreamMode(),
style: const TextStyle(
fontSize: 14,
color: Colors.grey
),
),
],
),
)
),
)
],
),
);
}
}

View file

@ -0,0 +1,110 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart';
class DnsModeModal extends StatefulWidget {
final String upstreamMode;
final void Function(String) onConfirm;
const DnsModeModal({
Key? key,
required this.upstreamMode,
required this.onConfirm,
}) : super(key: key);
@override
State<DnsModeModal> createState() => _DnsModeModalState();
}
class _DnsModeModalState extends State<DnsModeModal> {
String upstreamMode = "";
@override
void initState() {
upstreamMode = widget.upstreamMode;
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
height: 660,
decoration: BoxDecoration(
color: Theme.of(context).dialogBackgroundColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(28),
topRight: Radius.circular(28)
)
),
child: ListView(
physics: const NeverScrollableScrollPhysics(),
children: [
const Padding(
padding: EdgeInsets.only(top: 28, bottom: 20),
child: Icon(
Icons.dns_rounded,
size: 26,
),
),
Text(
AppLocalizations.of(context)!.dnsMode,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 24
),
),
const SizedBox(height: 10),
CustomRadioListTile(
groupValue: upstreamMode,
value: "load_balancing",
radioBackgroundColor: Theme.of(context).dialogBackgroundColor,
title: AppLocalizations.of(context)!.loadBalancing,
subtitle: AppLocalizations.of(context)!.loadBalancingDescription,
onChanged: (value) => setState(() => upstreamMode = value),
),
CustomRadioListTile(
groupValue: upstreamMode,
value: "parallel_requests",
radioBackgroundColor: Theme.of(context).dialogBackgroundColor,
title: AppLocalizations.of(context)!.parallelRequests,
subtitle: AppLocalizations.of(context)!.parallelRequestsDescription,
onChanged: (value) => setState(() => upstreamMode = value),
),
CustomRadioListTile(
groupValue: upstreamMode,
value: "fastest_ip_address",
radioBackgroundColor: Theme.of(context).dialogBackgroundColor,
title: AppLocalizations.of(context)!.fastestIpAddress,
subtitle: AppLocalizations.of(context)!.fastestIpAddressDescription,
onChanged: (value) => setState(() => upstreamMode = value),
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 20,
right: 20
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.close)
),
const SizedBox(width: 20),
TextButton(
onPressed: () {
Navigator.pop(context);
widget.onConfirm(upstreamMode);
},
child: Text(AppLocalizations.of(context)!.confirm)
),
],
),
),
],
),
);
}
}

View file

@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/settings/server_info/server_info.da
import 'package:adguard_home_manager/screens/settings/access_settings/access_settings.dart';
import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart';
import 'package:adguard_home_manager/screens/settings/section_label.dart';
import 'package:adguard_home_manager/screens/settings/dns/dns.dart';
import 'package:adguard_home_manager/screens/settings/dns_rewrites/dns_rewrites.dart';
import 'package:adguard_home_manager/screens/settings/appbar.dart';
import 'package:adguard_home_manager/screens/servers/servers.dart';
@ -113,6 +114,18 @@ class Settings extends StatelessWidget {
)
},
),
CustomListTile(
leadingIcon: Icons.dns_rounded,
label: AppLocalizations.of(context)!.dnsSettings,
description: AppLocalizations.of(context)!.dnsSettingsDescription,
onTap: () => {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const DnsSettings()
)
)
},
),
CustomListTile(
leadingIcon: Icons.route_rounded,
label: AppLocalizations.of(context)!.dnsRewrites,

View file

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class CustomRadio extends StatelessWidget {
final int value;
final int groupValue;
final Function(int)? onChange;
final dynamic value;
final dynamic groupValue;
final Function(dynamic)? onChange;
final Color backgroundColor;
const CustomRadio({
@ -20,8 +20,8 @@ class CustomRadio extends StatelessWidget {
alignment: Alignment.center,
children: [
Container(
width: 20,
height: 20,
width: 18,
height: 18,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
color: value == groupValue
@ -32,16 +32,18 @@ class CustomRadio extends StatelessWidget {
),
),
Container(
width: 16,
height: 16,
width: 14,
height: 14,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(35),
color: backgroundColor
),
),
Container(
width: 12,
height: 12,
AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
width: 9.5,
height: 9.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: value == groupValue

View file

@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:adguard_home_manager/widgets/custom_radio.dart';
class CustomRadioListTile extends StatelessWidget {
final String groupValue;
final String value;
final Color radioBackgroundColor;
final String title;
final String? subtitle;
final void Function(String) onChanged;
const CustomRadioListTile({
Key? key,
required this.groupValue,
required this.value,
required this.radioBackgroundColor,
required this.title,
this.subtitle,
required this.onChanged,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () => onChanged(value),
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
const SizedBox(width: 10),
CustomRadio(
value: value,
groupValue: groupValue,
backgroundColor: radioBackgroundColor,
),
const SizedBox(width: 30),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: MediaQuery.of(context).size.width-110,
child: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16
),
),
),
if (subtitle != null) ...[
const SizedBox(height: 5),
SizedBox(
width: MediaQuery.of(context).size.width-110,
child: Text(
subtitle!,
style: const TextStyle(
color: Colors.grey,
fontSize: 14
),
),
),
]
],
)
],
),
),
),
);
}
}