mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-25 16:26:07 +00:00
Added cache configuration and changed added client validation
This commit is contained in:
parent
569ab7d569
commit
313b76740a
11 changed files with 302 additions and 167 deletions
|
@ -718,5 +718,12 @@
|
||||||
"noData": "No data",
|
"noData": "No data",
|
||||||
"unblockClient": "Unblock client",
|
"unblockClient": "Unblock client",
|
||||||
"blockingClient": "Blocking client...",
|
"blockingClient": "Blocking client...",
|
||||||
"unblockingClient": "Unblocking client..."
|
"unblockingClient": "Unblocking client...",
|
||||||
|
"upstreamDnsCacheConfiguration": "Configuración de la caché DNS upstream",
|
||||||
|
"enableDnsCachingClient": "Enable DNS caching for this client",
|
||||||
|
"dnsCacheSize": "DNS cache size",
|
||||||
|
"nameInvalid": "Name is required",
|
||||||
|
"oneIdentifierRequired": "At least one identifier is required",
|
||||||
|
"dnsCacheNumber": "DNS cache size must be a number",
|
||||||
|
"errors": "Errors"
|
||||||
}
|
}
|
|
@ -718,5 +718,12 @@
|
||||||
"noData": "No hay datos",
|
"noData": "No hay datos",
|
||||||
"unblockClient": "Desbloquear cliente",
|
"unblockClient": "Desbloquear cliente",
|
||||||
"blockingClient": "Bloqueando cliente...",
|
"blockingClient": "Bloqueando cliente...",
|
||||||
"unblockingClient": "Desbloqueando cliente..."
|
"unblockingClient": "Desbloqueando cliente...",
|
||||||
|
"upstreamDnsCacheConfiguration": "Configuración de la caché DNS upstream",
|
||||||
|
"enableDnsCachingClient": "Habilitar caché de DNS para este cliente",
|
||||||
|
"dnsCacheSize": "Tamaño de caché de DNS",
|
||||||
|
"nameInvalid": "Se requiere un nombre",
|
||||||
|
"oneIdentifierRequired": "Se require al menos un identificador",
|
||||||
|
"dnsCacheNumber": "El tamaño de caché de DNS debe ser un número",
|
||||||
|
"errors": "Errores"
|
||||||
}
|
}
|
|
@ -89,6 +89,8 @@ class Client {
|
||||||
final SafeSearch? safeSearch;
|
final SafeSearch? safeSearch;
|
||||||
final bool? ignoreQuerylog;
|
final bool? ignoreQuerylog;
|
||||||
final bool? ignoreStatistics;
|
final bool? ignoreStatistics;
|
||||||
|
final bool? upstreamsCacheEnabled;
|
||||||
|
final int? upstreamsCacheSize;
|
||||||
|
|
||||||
Client({
|
Client({
|
||||||
required this.name,
|
required this.name,
|
||||||
|
@ -104,6 +106,8 @@ class Client {
|
||||||
required this.safeSearch,
|
required this.safeSearch,
|
||||||
required this.ignoreQuerylog,
|
required this.ignoreQuerylog,
|
||||||
required this.ignoreStatistics,
|
required this.ignoreStatistics,
|
||||||
|
required this.upstreamsCacheEnabled,
|
||||||
|
required this.upstreamsCacheSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Client.fromJson(Map<String, dynamic> json) => Client(
|
factory Client.fromJson(Map<String, dynamic> json) => Client(
|
||||||
|
@ -121,7 +125,9 @@ class Client {
|
||||||
? SafeSearch.fromJson(json["safe_search"])
|
? SafeSearch.fromJson(json["safe_search"])
|
||||||
: null,
|
: null,
|
||||||
ignoreQuerylog: json["ignore_querylog"],
|
ignoreQuerylog: json["ignore_querylog"],
|
||||||
ignoreStatistics: json["ignore_statistics"]
|
ignoreStatistics: json["ignore_statistics"],
|
||||||
|
upstreamsCacheEnabled: json["upstreams_cache_enabled"],
|
||||||
|
upstreamsCacheSize: json["upstreams_cache_size"]
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
@ -138,5 +144,7 @@ class Client {
|
||||||
"use_global_settings": useGlobalSettings,
|
"use_global_settings": useGlobalSettings,
|
||||||
"ignore_querylog": ignoreQuerylog,
|
"ignore_querylog": ignoreQuerylog,
|
||||||
"ignore_statistics": ignoreStatistics,
|
"ignore_statistics": ignoreStatistics,
|
||||||
|
"upstreams_cache_enabled": upstreamsCacheEnabled,
|
||||||
|
"upstreams_cache_size": upstreamsCacheSize
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ class BlockedServicesSection extends StatelessWidget {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
|
@ -31,8 +31,8 @@ class BlockedServicesSection extends StatelessWidget {
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 20,
|
horizontal: 16,
|
||||||
vertical: 5
|
vertical: 6
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
@ -56,7 +56,7 @@ class BlockedServicesSection extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 12),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
@ -69,7 +69,7 @@ class BlockedServicesSection extends StatelessWidget {
|
||||||
: null,
|
: null,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 8, horizontal: 24
|
vertical: 8, horizontal: 32
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
@ -12,6 +9,7 @@ import 'package:adguard_home_manager/screens/clients/client/settings_tile.dart';
|
||||||
import 'package:adguard_home_manager/screens/clients/client/tags_section.dart';
|
import 'package:adguard_home_manager/screens/clients/client/tags_section.dart';
|
||||||
import 'package:adguard_home_manager/screens/clients/client/upstream_servers_section.dart';
|
import 'package:adguard_home_manager/screens/clients/client/upstream_servers_section.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart';
|
||||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||||
import 'package:adguard_home_manager/widgets/section_label.dart';
|
import 'package:adguard_home_manager/widgets/section_label.dart';
|
||||||
|
|
||||||
|
@ -22,7 +20,6 @@ class ClientForm extends StatelessWidget {
|
||||||
final bool isFullScreen;
|
final bool isFullScreen;
|
||||||
final Client? client;
|
final Client? client;
|
||||||
final TextEditingController nameController;
|
final TextEditingController nameController;
|
||||||
final void Function(bool) updateValidValues;
|
|
||||||
final List<ControllerListItem> identifiersControllers;
|
final List<ControllerListItem> identifiersControllers;
|
||||||
final List<String> selectedTags;
|
final List<String> selectedTags;
|
||||||
final bool useGlobalSettingsFiltering;
|
final bool useGlobalSettingsFiltering;
|
||||||
|
@ -50,13 +47,17 @@ class ClientForm extends StatelessWidget {
|
||||||
final void Function(bool) updateIgnoreClientQueryLog;
|
final void Function(bool) updateIgnoreClientQueryLog;
|
||||||
final bool ignoreClientStatistics;
|
final bool ignoreClientStatistics;
|
||||||
final void Function(bool) updateIgnoreClientStatistics;
|
final void Function(bool) updateIgnoreClientStatistics;
|
||||||
|
final bool enableDnsCache;
|
||||||
|
final void Function(bool) updateEnableDnsCache;
|
||||||
|
final TextEditingController dnsCacheField;
|
||||||
|
final String? dnsCacheError;
|
||||||
|
final void Function(String?) updateDnsCacheError;
|
||||||
|
|
||||||
const ClientForm({
|
const ClientForm({
|
||||||
super.key,
|
super.key,
|
||||||
required this.isFullScreen,
|
required this.isFullScreen,
|
||||||
required this.client,
|
required this.client,
|
||||||
required this.nameController,
|
required this.nameController,
|
||||||
required this.updateValidValues,
|
|
||||||
required this.identifiersControllers,
|
required this.identifiersControllers,
|
||||||
required this.selectedTags,
|
required this.selectedTags,
|
||||||
required this.useGlobalSettingsFiltering,
|
required this.useGlobalSettingsFiltering,
|
||||||
|
@ -84,26 +85,24 @@ class ClientForm extends StatelessWidget {
|
||||||
required this.ignoreClientStatistics,
|
required this.ignoreClientStatistics,
|
||||||
required this.updateIgnoreClientQueryLog,
|
required this.updateIgnoreClientQueryLog,
|
||||||
required this.updateIgnoreClientStatistics,
|
required this.updateIgnoreClientStatistics,
|
||||||
|
required this.enableDnsCache,
|
||||||
|
required this.updateEnableDnsCache,
|
||||||
|
required this.dnsCacheField,
|
||||||
|
required this.dnsCacheError,
|
||||||
|
required this.updateDnsCacheError,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
return Column(
|
||||||
padding: const EdgeInsets.only(top: 0),
|
|
||||||
children: [
|
children: [
|
||||||
if (isFullScreen == true) const SizedBox(height: 24),
|
const SizedBox(height: 8),
|
||||||
if (isFullScreen == false) const SizedBox(height: 6),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
enabled: client != null ? false : true,
|
enabled: client != null ? false : true,
|
||||||
controller: nameController,
|
controller: nameController,
|
||||||
onChanged: (_) => updateValidValues(
|
onChanged: (_) => {},
|
||||||
checkValidValues(
|
|
||||||
identifiersControllers: identifiersControllers,
|
|
||||||
nameController: nameController
|
|
||||||
)
|
|
||||||
),
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefixIcon: const Icon(Icons.badge_rounded),
|
prefixIcon: const Icon(Icons.badge_rounded),
|
||||||
border: const OutlineInputBorder(
|
border: const OutlineInputBorder(
|
||||||
|
@ -117,7 +116,7 @@ class ClientForm extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.tags,
|
label: AppLocalizations.of(context)!.tags,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
),
|
),
|
||||||
TagsSection(
|
TagsSection(
|
||||||
selectedTags: selectedTags,
|
selectedTags: selectedTags,
|
||||||
|
@ -127,28 +126,17 @@ class ClientForm extends StatelessWidget {
|
||||||
identifiersControllers: identifiersControllers,
|
identifiersControllers: identifiersControllers,
|
||||||
onUpdateIdentifiersControllers: (c) {
|
onUpdateIdentifiersControllers: (c) {
|
||||||
updateIdentifiersControllers(c);
|
updateIdentifiersControllers(c);
|
||||||
updateValidValues(
|
|
||||||
checkValidValues(
|
|
||||||
nameController: nameController,
|
|
||||||
identifiersControllers: identifiersControllers
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onCheckValidValues: () => updateValidValues(
|
onCheckValidValues: () => {}
|
||||||
checkValidValues(
|
|
||||||
identifiersControllers: identifiersControllers,
|
|
||||||
nameController: nameController
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.settings,
|
label: AppLocalizations.of(context)!.settings,
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 24, right: 24, top: 12, bottom: 24
|
left: 16, right: 16, top: 12, bottom: 24
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
|
@ -157,8 +145,8 @@ class ClientForm extends StatelessWidget {
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 20,
|
horizontal: 16,
|
||||||
vertical: 5
|
vertical: 6
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
@ -182,7 +170,7 @@ class ClientForm extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 8),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
label: AppLocalizations.of(context)!.enableFiltering,
|
label: AppLocalizations.of(context)!.enableFiltering,
|
||||||
value: enableFiltering,
|
value: enableFiltering,
|
||||||
|
@ -204,7 +192,7 @@ class ClientForm extends StatelessWidget {
|
||||||
CustomListTile(
|
CustomListTile(
|
||||||
title: AppLocalizations.of(context)!.safeSearch,
|
title: AppLocalizations.of(context)!.safeSearch,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 42,
|
horizontal: 34,
|
||||||
vertical: 16
|
vertical: 16
|
||||||
),
|
),
|
||||||
trailing: Padding(
|
trailing: Padding(
|
||||||
|
@ -228,15 +216,15 @@ class ClientForm extends StatelessWidget {
|
||||||
),
|
),
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.queryLogsAndStatistics,
|
label: AppLocalizations.of(context)!.queryLogsAndStatistics,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
),
|
),
|
||||||
CustomSwitchListTile(
|
CustomSwitchListTile(
|
||||||
title: AppLocalizations.of(context)!.ignoreClientQueryLog,
|
title: AppLocalizations.of(context)!.ignoreClientQueryLog,
|
||||||
value: ignoreClientQueryLog,
|
value: ignoreClientQueryLog,
|
||||||
onChanged: updateIgnoreClientQueryLog,
|
onChanged: updateIgnoreClientQueryLog,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 24,
|
horizontal: 16,
|
||||||
vertical: 4
|
vertical: 6
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
CustomSwitchListTile(
|
CustomSwitchListTile(
|
||||||
|
@ -244,13 +232,13 @@ class ClientForm extends StatelessWidget {
|
||||||
value: ignoreClientStatistics,
|
value: ignoreClientStatistics,
|
||||||
onChanged: updateIgnoreClientStatistics,
|
onChanged: updateIgnoreClientStatistics,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 24,
|
horizontal: 16,
|
||||||
vertical: 4
|
vertical: 6
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.blockedServices,
|
label: AppLocalizations.of(context)!.blockedServices,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
),
|
),
|
||||||
BlockedServicesSection(
|
BlockedServicesSection(
|
||||||
useGlobalSettingsServices: useGlobalSettingsServices,
|
useGlobalSettingsServices: useGlobalSettingsServices,
|
||||||
|
@ -260,15 +248,40 @@ class ClientForm extends StatelessWidget {
|
||||||
),
|
),
|
||||||
UpstreamServersSection(
|
UpstreamServersSection(
|
||||||
upstreamServers: upstreamServers,
|
upstreamServers: upstreamServers,
|
||||||
onCheckValidValues: () => updateValidValues(
|
onCheckValidValues: () => {},
|
||||||
checkValidValues(
|
|
||||||
identifiersControllers: identifiersControllers,
|
|
||||||
nameController: nameController
|
|
||||||
)
|
|
||||||
),
|
|
||||||
onUpdateUpstreamServers: updateUpstreamServers
|
onUpdateUpstreamServers: updateUpstreamServers
|
||||||
),
|
),
|
||||||
SizedBox(height: Platform.isIOS ? 48 : 24)
|
SectionLabel(
|
||||||
|
label: AppLocalizations.of(context)!.upstreamDnsCacheConfiguration,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
|
),
|
||||||
|
CustomSwitchListTile(
|
||||||
|
title: AppLocalizations.of(context)!.enableDnsCachingClient,
|
||||||
|
value: enableDnsCache,
|
||||||
|
onChanged: updateEnableDnsCache,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 6
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: dnsCacheField,
|
||||||
|
onChanged: (v) => updateDnsCacheError(!validateNumber(v) ? AppLocalizations.of(context)!.invalidValue : null),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: const Icon(Icons.storage_rounded),
|
||||||
|
border: const OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(10)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
labelText: AppLocalizations.of(context)!.dnsCacheSize,
|
||||||
|
errorText: dnsCacheError
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ class ClientScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ClientScreenState extends State<ClientScreen> {
|
class _ClientScreenState extends State<ClientScreen> {
|
||||||
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
final Uuid uuid = const Uuid();
|
final Uuid uuid = const Uuid();
|
||||||
|
|
||||||
bool validValues = false;
|
bool validValues = false;
|
||||||
|
@ -76,6 +78,15 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
bool _ignoreClientQueryLog = false;
|
bool _ignoreClientQueryLog = false;
|
||||||
bool _ignoreClientStatistics = false;
|
bool _ignoreClientStatistics = false;
|
||||||
|
|
||||||
|
bool _enableDnsCache = false;
|
||||||
|
final _dnsCacheField = TextEditingController();
|
||||||
|
String? _dnsCacheError;
|
||||||
|
|
||||||
|
// VALIDATIONS
|
||||||
|
bool _nameValid = true;
|
||||||
|
bool _identifiersValid = true;
|
||||||
|
bool _dnsCacheValid = true;
|
||||||
|
|
||||||
void enableDisableGlobalSettingsFiltering() {
|
void enableDisableGlobalSettingsFiltering() {
|
||||||
if (useGlobalSettingsFiltering == true) {
|
if (useGlobalSettingsFiltering == true) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -125,6 +136,10 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
)).toList();
|
)).toList();
|
||||||
_ignoreClientQueryLog = widget.client!.ignoreQuerylog ?? false;
|
_ignoreClientQueryLog = widget.client!.ignoreQuerylog ?? false;
|
||||||
_ignoreClientStatistics = widget.client!.ignoreStatistics ?? false;
|
_ignoreClientStatistics = widget.client!.ignoreStatistics ?? false;
|
||||||
|
_enableDnsCache = widget.client!.upstreamsCacheEnabled ?? false;
|
||||||
|
_dnsCacheField.text = widget.client!.upstreamsCacheSize != null
|
||||||
|
? widget.client!.upstreamsCacheSize.toString()
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
@ -147,20 +162,37 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
upstreams: List<String>.from(upstreamServers.map((e) => e.controller.text)),
|
upstreams: List<String>.from(upstreamServers.map((e) => e.controller.text)),
|
||||||
tags: selectedTags,
|
tags: selectedTags,
|
||||||
ignoreQuerylog: _ignoreClientQueryLog,
|
ignoreQuerylog: _ignoreClientQueryLog,
|
||||||
ignoreStatistics: _ignoreClientStatistics
|
ignoreStatistics: _ignoreClientStatistics,
|
||||||
|
upstreamsCacheEnabled: _enableDnsCache,
|
||||||
|
upstreamsCacheSize: _dnsCacheField.text != ""
|
||||||
|
? int.parse(_dnsCacheField.text)
|
||||||
|
: null
|
||||||
);
|
);
|
||||||
widget.onConfirm(client);
|
widget.onConfirm(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void validateValues() {
|
||||||
|
_nameValid = nameController.text != '';
|
||||||
|
_identifiersValid = identifiersControllers.isNotEmpty && identifiersControllers[0].controller.text != '';
|
||||||
|
_dnsCacheValid = (_dnsCacheField.text == "" || _dnsCacheField.text != "" && RegExp(r'^\d+$').hasMatch(_dnsCacheField.text));
|
||||||
|
if (_nameValid && _identifiersValid && _dnsCacheValid) {
|
||||||
|
createClient();
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_scrollController.animateTo(
|
||||||
|
0,
|
||||||
|
curve: Curves.easeOut,
|
||||||
|
duration: const Duration(milliseconds: 500)
|
||||||
|
);
|
||||||
|
setState(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> actions() {
|
List<Widget> actions() {
|
||||||
return [
|
return [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: validValues == true
|
onPressed: validateValues,
|
||||||
? () {
|
|
||||||
createClient();
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
icon: const Icon(Icons.save_rounded),
|
icon: const Icon(Icons.save_rounded),
|
||||||
tooltip: AppLocalizations.of(context)!.save,
|
tooltip: AppLocalizations.of(context)!.save,
|
||||||
),
|
),
|
||||||
|
@ -193,11 +225,18 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
actions: actions(),
|
actions: actions(),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: ClientForm(
|
child: ListView(
|
||||||
|
controller: _scrollController,
|
||||||
|
children: [
|
||||||
|
if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors(
|
||||||
|
nameValid: _nameValid,
|
||||||
|
identifiersValid: _identifiersValid,
|
||||||
|
dnsCacheValid: _dnsCacheValid
|
||||||
|
),
|
||||||
|
ClientForm(
|
||||||
isFullScreen: true,
|
isFullScreen: true,
|
||||||
client: widget.client,
|
client: widget.client,
|
||||||
nameController: nameController,
|
nameController: nameController,
|
||||||
updateValidValues: (v) => setState(() => validValues = v),
|
|
||||||
identifiersControllers: identifiersControllers,
|
identifiersControllers: identifiersControllers,
|
||||||
selectedTags: selectedTags,
|
selectedTags: selectedTags,
|
||||||
useGlobalSettingsFiltering: useGlobalSettingsFiltering,
|
useGlobalSettingsFiltering: useGlobalSettingsFiltering,
|
||||||
|
@ -225,6 +264,13 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
ignoreClientStatistics: _ignoreClientStatistics,
|
ignoreClientStatistics: _ignoreClientStatistics,
|
||||||
updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v),
|
updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v),
|
||||||
updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v),
|
updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v),
|
||||||
|
enableDnsCache: _enableDnsCache,
|
||||||
|
updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v),
|
||||||
|
dnsCacheField: _dnsCacheField,
|
||||||
|
dnsCacheError: _dnsCacheError,
|
||||||
|
updateDnsCacheError: (v) => setState(() => _dnsCacheError = v)
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -264,11 +310,18 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: ClientForm(
|
child: ListView(
|
||||||
|
controller: _scrollController,
|
||||||
|
children: [
|
||||||
|
if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors(
|
||||||
|
nameValid: _nameValid,
|
||||||
|
identifiersValid: _identifiersValid,
|
||||||
|
dnsCacheValid: _dnsCacheValid
|
||||||
|
),
|
||||||
|
ClientForm(
|
||||||
isFullScreen: false,
|
isFullScreen: false,
|
||||||
client: widget.client,
|
client: widget.client,
|
||||||
nameController: nameController,
|
nameController: nameController,
|
||||||
updateValidValues: (v) => setState(() => validValues = v),
|
|
||||||
identifiersControllers: identifiersControllers,
|
identifiersControllers: identifiersControllers,
|
||||||
selectedTags: selectedTags,
|
selectedTags: selectedTags,
|
||||||
useGlobalSettingsFiltering: useGlobalSettingsFiltering,
|
useGlobalSettingsFiltering: useGlobalSettingsFiltering,
|
||||||
|
@ -296,6 +349,13 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
ignoreClientStatistics: _ignoreClientStatistics,
|
ignoreClientStatistics: _ignoreClientStatistics,
|
||||||
updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v),
|
updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v),
|
||||||
updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v),
|
updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v),
|
||||||
|
enableDnsCache: _enableDnsCache,
|
||||||
|
updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v),
|
||||||
|
dnsCacheField: _dnsCacheField,
|
||||||
|
dnsCacheError: _dnsCacheError,
|
||||||
|
updateDnsCacheError: (v) => setState(() => _dnsCacheError = v)
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -306,3 +366,56 @@ class _ClientScreenState extends State<ClientScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _Errors extends StatelessWidget {
|
||||||
|
final bool nameValid;
|
||||||
|
final bool identifiersValid;
|
||||||
|
final bool dnsCacheValid;
|
||||||
|
|
||||||
|
const _Errors({
|
||||||
|
required this.nameValid,
|
||||||
|
required this.identifiersValid,
|
||||||
|
required this.dnsCacheValid,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: Colors.red.withOpacity(0.2),
|
||||||
|
margin: const EdgeInsets.all(16),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.errors,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
if (!nameValid) Text(
|
||||||
|
"● ${AppLocalizations.of(context)!.nameInvalid}",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!identifiersValid) Text(
|
||||||
|
"● ${AppLocalizations.of(context)!.oneIdentifierRequired}",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!dnsCacheValid) Text(
|
||||||
|
"● ${AppLocalizations.of(context)!.dnsCacheNumber}",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,22 +74,6 @@ void openSafeSearchModal({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkValidValues({
|
|
||||||
required TextEditingController nameController,
|
|
||||||
required List<ControllerListItem> identifiersControllers
|
|
||||||
}) {
|
|
||||||
if (
|
|
||||||
nameController.text != '' &&
|
|
||||||
identifiersControllers.isNotEmpty &&
|
|
||||||
identifiersControllers[0].controller.text != ''
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void openClientFormModal({
|
void openClientFormModal({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required double width,
|
required double width,
|
||||||
|
@ -124,3 +108,9 @@ void openClientFormModal({
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validateNumber(String value) {
|
||||||
|
if (value == "") return true;
|
||||||
|
final regexp = RegExp(r'^\d+$');
|
||||||
|
return regexp.hasMatch(value);
|
||||||
|
}
|
|
@ -11,11 +11,11 @@ class IdentifiersSection extends StatefulWidget {
|
||||||
final void Function() onCheckValidValues;
|
final void Function() onCheckValidValues;
|
||||||
|
|
||||||
const IdentifiersSection({
|
const IdentifiersSection({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.identifiersControllers,
|
required this.identifiersControllers,
|
||||||
required this.onUpdateIdentifiersControllers,
|
required this.onUpdateIdentifiersControllers,
|
||||||
required this.onCheckValidValues
|
required this.onCheckValidValues
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<IdentifiersSection> createState() => _IdentifiersSectionState();
|
State<IdentifiersSection> createState() => _IdentifiersSectionState();
|
||||||
|
@ -34,11 +34,11 @@ class _IdentifiersSectionState extends State<IdentifiersSection> {
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.identifiers,
|
label: AppLocalizations.of(context)!.identifiers,
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 24, right: 24, top: 24, bottom: 12
|
left: 16, right: 16, top: 24, bottom: 12
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 20),
|
padding: const EdgeInsets.only(right: 10),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () => widget.onUpdateIdentifiersControllers([
|
onPressed: () => widget.onUpdateIdentifiersControllers([
|
||||||
...widget.identifiersControllers,
|
...widget.identifiersControllers,
|
||||||
|
@ -54,7 +54,7 @@ class _IdentifiersSectionState extends State<IdentifiersSection> {
|
||||||
),
|
),
|
||||||
if (widget.identifiersControllers.isNotEmpty) ...widget.identifiersControllers.map((controller) => Padding(
|
if (widget.identifiersControllers.isNotEmpty) ...widget.identifiersControllers.map((controller) => Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 12, bottom: 12, left: 24, right: 20
|
top: 12, bottom: 12, left: 16, right: 10
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
@ -75,9 +75,9 @@ class _IdentifiersSectionState extends State<IdentifiersSection> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 12),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 25),
|
padding: const EdgeInsets.only(bottom: 24),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () => widget.onUpdateIdentifiersControllers(
|
onPressed: () => widget.onUpdateIdentifiersControllers(
|
||||||
widget.identifiersControllers.where((e) => e.id != controller.id).toList()
|
widget.identifiersControllers.where((e) => e.id != controller.id).toList()
|
||||||
|
@ -87,7 +87,7 @@ class _IdentifiersSectionState extends State<IdentifiersSection> {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)).toList(),
|
)),
|
||||||
if (widget.identifiersControllers.isEmpty) Container(
|
if (widget.identifiersControllers.isEmpty) Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
|
@ -7,12 +7,12 @@ class SettingsTile extends StatelessWidget {
|
||||||
final bool useGlobalSettingsFiltering;
|
final bool useGlobalSettingsFiltering;
|
||||||
|
|
||||||
const SettingsTile({
|
const SettingsTile({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.value,
|
required this.value,
|
||||||
this.onChange,
|
this.onChange,
|
||||||
required this.useGlobalSettingsFiltering
|
required this.useGlobalSettingsFiltering
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -23,10 +23,7 @@ class SettingsTile extends StatelessWidget {
|
||||||
? value != null ? () => onChange!(!value!) : null
|
? value != null ? () => onChange!(!value!) : null
|
||||||
: null,
|
: null,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 6),
|
||||||
horizontal: 42,
|
|
||||||
vertical: 5
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -7,10 +7,10 @@ class TagsSection extends StatelessWidget {
|
||||||
final void Function(List<String>) onTagsSelected;
|
final void Function(List<String>) onTagsSelected;
|
||||||
|
|
||||||
const TagsSection({
|
const TagsSection({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.selectedTags,
|
required this.selectedTags,
|
||||||
required this.onTagsSelected
|
required this.onTagsSelected
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -24,7 +24,7 @@ class TagsSection extends StatelessWidget {
|
||||||
) ,
|
) ,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 0, horizontal: 24
|
vertical: 0, horizontal: 16
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -11,11 +11,11 @@ class UpstreamServersSection extends StatefulWidget {
|
||||||
final void Function(List<ControllerListItem>) onUpdateUpstreamServers;
|
final void Function(List<ControllerListItem>) onUpdateUpstreamServers;
|
||||||
|
|
||||||
const UpstreamServersSection({
|
const UpstreamServersSection({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.upstreamServers,
|
required this.upstreamServers,
|
||||||
required this.onCheckValidValues,
|
required this.onCheckValidValues,
|
||||||
required this.onUpdateUpstreamServers
|
required this.onUpdateUpstreamServers
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<UpstreamServersSection> createState() => _UpstreamServersSectionState();
|
State<UpstreamServersSection> createState() => _UpstreamServersSectionState();
|
||||||
|
@ -33,10 +33,10 @@ class _UpstreamServersSectionState extends State<UpstreamServersSection> {
|
||||||
children: [
|
children: [
|
||||||
SectionLabel(
|
SectionLabel(
|
||||||
label: AppLocalizations.of(context)!.upstreamServers,
|
label: AppLocalizations.of(context)!.upstreamServers,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 20),
|
padding: const EdgeInsets.only(right: 12),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () => setState(() => widget.upstreamServers.add(
|
onPressed: () => setState(() => widget.upstreamServers.add(
|
||||||
ControllerListItem(
|
ControllerListItem(
|
||||||
|
@ -50,7 +50,7 @@ class _UpstreamServersSectionState extends State<UpstreamServersSection> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (widget.upstreamServers.isNotEmpty) ...widget.upstreamServers.map((controller) => Padding(
|
if (widget.upstreamServers.isNotEmpty) ...widget.upstreamServers.map((controller) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.only(left: 16, right: 12),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 20),
|
padding: const EdgeInsets.only(bottom: 20),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -71,7 +71,7 @@ class _UpstreamServersSectionState extends State<UpstreamServersSection> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 12),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => widget.onUpdateUpstreamServers(
|
onPressed: () => widget.onUpdateUpstreamServers(
|
||||||
widget.upstreamServers.where((e) => e.id != controller.id).toList()
|
widget.upstreamServers.where((e) => e.id != controller.id).toList()
|
||||||
|
@ -81,7 +81,7 @@ class _UpstreamServersSectionState extends State<UpstreamServersSection> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)).toList(),
|
)),
|
||||||
if (widget.upstreamServers.isEmpty) Container(
|
if (widget.upstreamServers.isEmpty) Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
Loading…
Add table
Reference in a new issue