From 05e5255467960827d0c2bedf0cfb1f2e1a6ddfe5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 15:43:19 +0100 Subject: [PATCH] Refactor client form code --- lib/screens/clients/client/client_form.dart | 265 +++++++++++++ lib/screens/clients/client/client_screen.dart | 353 ++++++------------ .../client/client_screen_functions.dart | 4 +- .../clients/client/identifiers_section.dart | 25 +- .../client/upstream_servers_section.dart | 21 +- 5 files changed, 401 insertions(+), 267 deletions(-) create mode 100644 lib/screens/clients/client/client_form.dart diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart new file mode 100644 index 0000000..ff4db9a --- /dev/null +++ b/lib/screens/clients/client/client_form.dart @@ -0,0 +1,265 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/clients/client/blocked_services_section.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; +import 'package:adguard_home_manager/screens/clients/client/identifiers_section.dart'; +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/upstream_servers_section.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/functions/compare_versions.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/models/safe_search.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class ClientForm extends StatelessWidget { + final bool isFullScreen; + final Client? client; + final TextEditingController nameController; + final void Function(bool) updateValidValues; + final List identifiersControllers; + final List selectedTags; + final bool useGlobalSettingsFiltering; + final bool? enableFiltering; + final bool? enableSafeBrowsing; + final bool? enableParentalControl; + final bool? enableSafeSearch; + final SafeSearch? safeSearch; + final SafeSearch defaultSafeSearch; + final bool useGlobalSettingsServices; + final List blockedServices; + final void Function(List) updateBlockedServices; + final List upstreamServers; + final void Function(List) updateUpstreamServers; + final void Function(List) updateSelectedTags; + final void Function(List) updateIdentifiersControllers; + final void Function() enableDisableGlobalSettingsFiltering; + final void Function(bool) updateEnableFiltering; + final void Function(bool) updateEnableSafeBrowsing; + final void Function(bool) updateEnableParentalControl; + final void Function(bool) updateEnableSafeSearch; + final void Function(SafeSearch) updateSafeSearch; + final void Function(bool) updateUseGlobalSettingsServices; + + const ClientForm({ + Key? key, + required this.isFullScreen, + required this.client, + required this.nameController, + required this.updateValidValues, + required this.identifiersControllers, + required this.selectedTags, + required this.useGlobalSettingsFiltering, + required this.enableFiltering, + required this.enableParentalControl, + required this.enableSafeBrowsing, + required this.enableSafeSearch, + required this.safeSearch, + required this.blockedServices, + required this.updateBlockedServices, + required this.upstreamServers, + required this.updateUpstreamServers, + required this.defaultSafeSearch, + required this.useGlobalSettingsServices, + required this.updateSelectedTags, + required this.updateIdentifiersControllers, + required this.enableDisableGlobalSettingsFiltering, + required this.updateEnableFiltering, + required this.updateEnableParentalControl, + required this.updateEnableSafeBrowsing, + required this.updateEnableSafeSearch, + required this.updateSafeSearch, + required this.updateUseGlobalSettingsServices, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + return ListView( + padding: const EdgeInsets.only(top: 0), + children: [ + if (isFullScreen == true) const SizedBox(height: 24), + if (isFullScreen == false) const SizedBox(height: 6), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + enabled: client != null ? false : true, + controller: nameController, + onChanged: (_) => updateValidValues( + checkValidValues( + identifiersControllers: identifiersControllers, + nameController: nameController + ) + ), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.badge_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.name, + ), + ), + ), + SectionLabel( + label: AppLocalizations.of(context)!.tags, + padding: const EdgeInsets.all(24), + ), + TagsSection( + selectedTags: selectedTags, + onTagsSelected: updateSelectedTags + ), + IdentifiersSection( + identifiersControllers: identifiersControllers, + onUpdateIdentifiersControllers: (c) { + updateIdentifiersControllers(c); + updateValidValues( + checkValidValues( + nameController: nameController, + identifiersControllers: identifiersControllers + ) + ); + }, + onCheckValidValues: () => updateValidValues( + checkValidValues( + identifiersControllers: identifiersControllers, + nameController: nameController + ) + ), + ), + SectionLabel( + label: AppLocalizations.of(context)!.settings, + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12, bottom: 24 + ) + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: enableDisableGlobalSettingsFiltering, + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 5 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.useGlobalSettings, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Switch( + value: useGlobalSettingsFiltering, + onChanged: (value) => enableDisableGlobalSettingsFiltering() + ) + ], + ), + ), + ), + ), + ), + const SizedBox(height: 10), + SettingsTile( + label: AppLocalizations.of(context)!.enableFiltering, + value: enableFiltering, + onChange: (value) => updateEnableFiltering(value), + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + ), + SettingsTile( + label: AppLocalizations.of(context)!.enableSafeBrowsing, + value: enableSafeBrowsing, + onChange: (value) => updateEnableSafeBrowsing(value), + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + ), + SettingsTile( + label: AppLocalizations.of(context)!.enableParentalControl, + value: enableParentalControl, + onChange: (value) => updateEnableParentalControl(value), + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + ), + if ( + serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ) CustomListTile( + title: AppLocalizations.of(context)!.safeSearch, + padding: const EdgeInsets.symmetric( + horizontal: 42, + vertical: 16 + ), + trailing: Padding( + padding: const EdgeInsets.only(right: 16), + child: Icon( + Icons.chevron_right_rounded, + color: useGlobalSettingsFiltering == true + ? Colors.grey + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + onTap: useGlobalSettingsFiltering == false + ? () => openSafeSearchModal( + context: context, + blockedServices: blockedServices, + defaultSafeSearch: defaultSafeSearch, + safeSearch: safeSearch, + onUpdateSafeSearch: updateSafeSearch + ) + : null, + ), + if ( + serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ) SettingsTile( + label: AppLocalizations.of(context)!.enableSafeSearch, + value: enableSafeSearch, + onChange: (value) => updateEnableSafeSearch(value), + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + ), + SectionLabel( + label: AppLocalizations.of(context)!.blockedServices, + padding: const EdgeInsets.all(24), + ), + BlockedServicesSection( + useGlobalSettingsServices: useGlobalSettingsServices, + blockedServices: blockedServices, + onUpdatedBlockedServices: updateBlockedServices, + onUpdateServicesGlobalSettings: updateUseGlobalSettingsServices, + ), + UpstreamServersSection( + upstreamServers: upstreamServers, + onCheckValidValues: () => updateValidValues( + checkValidValues( + identifiersControllers: identifiersControllers, + nameController: nameController + ) + ), + onUpdateUpstreamServers: updateUpstreamServers + ), + SizedBox(height: Platform.isIOS ? 48 : 24) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 4fcee53..243981c 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -3,14 +3,8 @@ import 'package:provider/provider.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/clients/client/upstream_servers_section.dart'; -import 'package:adguard_home_manager/screens/clients/client/identifiers_section.dart'; -import 'package:adguard_home_manager/screens/clients/client/blocked_services_section.dart'; -import 'package:adguard_home_manager/screens/clients/client/tags_section.dart'; -import 'package:adguard_home_manager/screens/clients/client/settings_tile.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_form.dart'; import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; @@ -18,6 +12,16 @@ import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; +class ControllerListItem { + final String id; + final TextEditingController controller; + + const ControllerListItem({ + required this.id, + required this.controller + }); +} + class ClientScreen extends StatefulWidget { final Client? client; final void Function(Client) onConfirm; @@ -45,11 +49,8 @@ class _ClientScreenState extends State { List selectedTags = []; - List> identifiersControllers = [ - { - 'id': 0, - 'controller': TextEditingController() - } + List identifiersControllers = [ + ControllerListItem(id: "0", controller: TextEditingController()) ]; bool useGlobalSettingsFiltering = true; @@ -72,10 +73,35 @@ class _ClientScreenState extends State { bool useGlobalSettingsServices = true; List blockedServices = []; - List> upstreamServers = []; + List upstreamServers = []; bool version = false; + void enableDisableGlobalSettingsFiltering() { + if (useGlobalSettingsFiltering == true) { + setState(() { + useGlobalSettingsFiltering = false; + + enableFiltering = false; + enableSafeBrowsing = false; + enableParentalControl = false; + enableSafeSearch = false; + safeSearch = defaultSafeSearch; + }); + } + else if (useGlobalSettingsFiltering == false) { + setState(() { + useGlobalSettingsFiltering = true; + + enableFiltering = null; + enableSafeBrowsing = null; + enableParentalControl = null; + enableSafeSearch = null; + safeSearch = null; + }); + } + } + @override void initState() { version = serverVersionIsAhead( @@ -89,10 +115,10 @@ class _ClientScreenState extends State { nameController.text = widget.client!.name; selectedTags = widget.client!.tags; - identifiersControllers = widget.client!.ids.map((e) => { - 'id': uuid.v4(), - 'controller': TextEditingController(text: e) - }).toList(); + identifiersControllers = widget.client!.ids.map((e) => ControllerListItem( + id: uuid.v4(), + controller: TextEditingController(text: e) + )).toList(); useGlobalSettingsFiltering = widget.client!.useGlobalSettings; enableFiltering = widget.client!.filteringEnabled; enableParentalControl = widget.client!.parentalEnabled; @@ -105,10 +131,10 @@ class _ClientScreenState extends State { } useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; blockedServices = widget.client!.blockedServices; - upstreamServers = widget.client!.upstreams.map((e) => { - 'id': uuid.v4(), - 'controller': TextEditingController(text: e) - }).toList(); + upstreamServers = widget.client!.upstreams.map((e) => ControllerListItem( + id: uuid.v4(), + controller: TextEditingController(text: e) + )).toList(); } super.initState(); } @@ -116,12 +142,11 @@ class _ClientScreenState extends State { @override Widget build(BuildContext context) { final clientsProvider = Provider.of(context); - final statusProvider = Provider.of(context); void createClient() { final Client client = Client( name: nameController.text, - ids: List.from(identifiersControllers.map((e) => e['controller'].text)), + ids: List.from(identifiersControllers.map((e) => e.controller.text)), useGlobalSettings: useGlobalSettingsFiltering, filteringEnabled: enableFiltering ?? false, parentalEnabled: enableParentalControl ?? false, @@ -130,51 +155,12 @@ class _ClientScreenState extends State { safeSearch: version == true ? safeSearch : null, useGlobalBlockedServices: useGlobalSettingsServices, blockedServices: blockedServices, - upstreams: List.from(upstreamServers.map((e) => e['controller'].text)), + upstreams: List.from(upstreamServers.map((e) => e.controller.text)), tags: selectedTags ); widget.onConfirm(client); } - void enableDisableGlobalSettingsFiltering() { - if (useGlobalSettingsFiltering == true) { - setState(() { - useGlobalSettingsFiltering = false; - - enableFiltering = false; - enableSafeBrowsing = false; - enableParentalControl = false; - enableSafeSearch = false; - safeSearch = defaultSafeSearch; - }); - } - else if (useGlobalSettingsFiltering == false) { - setState(() { - useGlobalSettingsFiltering = true; - - enableFiltering = null; - enableSafeBrowsing = null; - enableParentalControl = null; - enableSafeSearch = null; - safeSearch = null; - }); - } - } - - void updateServicesGlobalSettings(bool value) { - if (value == true) { - setState(() { - blockedServices = []; - useGlobalSettingsServices = true; - }); - } - else if (value == false) { - setState(() { - useGlobalSettingsServices = false; - }); - } - } - List actions() { return [ IconButton( @@ -199,184 +185,6 @@ class _ClientScreenState extends State { ]; } - Widget content(bool withPaddingTop) { - return ListView( - padding: const EdgeInsets.only(top: 0), - children: [ - if (withPaddingTop == true) const SizedBox(height: 24), - if (withPaddingTop == false) const SizedBox(height: 6), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - enabled: widget.client != null ? false : true, - controller: nameController, - onChanged: (_) => setState(() { - validValues = checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ); - }), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.badge_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.name, - ), - ), - ), - SectionLabel( - label: AppLocalizations.of(context)!.tags, - padding: const EdgeInsets.all(24), - ), - TagsSection( - selectedTags: selectedTags, - onTagsSelected: (tags) => setState(() => selectedTags = tags) - ), - IdentifiersSection( - identifiersControllers: identifiersControllers, - onUpdateIdentifiersControllers: (c) => setState(() { - identifiersControllers = c; - validValues = checkValidValues( - nameController: nameController, - identifiersControllers: identifiersControllers - ); - }), - onCheckValidValues: () => setState(() { - validValues = checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ); - }), - ), - SectionLabel( - label: AppLocalizations.of(context)!.settings, - padding: const EdgeInsets.only( - left: 24, right: 24, top: 12, bottom: 24 - ) - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Material( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: () => enableDisableGlobalSettingsFiltering(), - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 5 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.useGlobalSettings, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Switch( - value: useGlobalSettingsFiltering, - onChanged: (value) => enableDisableGlobalSettingsFiltering() - ) - ], - ), - ), - ), - ), - ), - const SizedBox(height: 10), - SettingsTile( - label: AppLocalizations.of(context)!.enableFiltering, - value: enableFiltering, - onChange: (value) => setState(() => enableFiltering = value), - useGlobalSettingsFiltering: useGlobalSettingsFiltering, - ), - SettingsTile( - label: AppLocalizations.of(context)!.enableSafeBrowsing, - value: enableSafeBrowsing, - onChange: (value) => setState(() => enableSafeBrowsing = value), - useGlobalSettingsFiltering: useGlobalSettingsFiltering, - ), - SettingsTile( - label: AppLocalizations.of(context)!.enableParentalControl, - value: enableParentalControl, - onChange: (value) => setState(() => enableParentalControl = value), - useGlobalSettingsFiltering: useGlobalSettingsFiltering, - ), - if ( - serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ) CustomListTile( - title: AppLocalizations.of(context)!.safeSearch, - padding: const EdgeInsets.symmetric( - horizontal: 42, - vertical: 16 - ), - trailing: Padding( - padding: const EdgeInsets.only(right: 16), - child: Icon( - Icons.chevron_right_rounded, - color: useGlobalSettingsFiltering == true - ? Colors.grey - : Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - onTap: useGlobalSettingsFiltering == false - ? () => openSafeSearchModal( - context: context, - blockedServices: blockedServices, - defaultSafeSearch: defaultSafeSearch, - safeSearch: safeSearch, - onUpdateSafeSearch: (s) => setState(() => safeSearch = s) - ) - : null, - ), - if ( - serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ) SettingsTile( - label: AppLocalizations.of(context)!.enableSafeSearch, - value: enableSafeSearch, - onChange: (value) => setState(() => enableSafeSearch = value), - useGlobalSettingsFiltering: useGlobalSettingsFiltering, - ), - SectionLabel( - label: AppLocalizations.of(context)!.blockedServices, - padding: const EdgeInsets.all(24), - ), - BlockedServicesSection( - useGlobalSettingsServices: useGlobalSettingsServices, - blockedServices: blockedServices, - onUpdatedBlockedServices: (s) => setState(() => blockedServices = s), - onUpdateServicesGlobalSettings: (v) => setState(() => useGlobalSettingsServices = v), - ), - UpstreamServersSection( - upstreamServers: upstreamServers, - onCheckValidValues: () => setState(() { - validValues = checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ); - }), - onUpdateUpstreamServers: (v) => setState(() => upstreamServers = v) - ), - const SizedBox(height: 20) - ], - ); - } - if (widget.fullScreen == true) { return Dialog.fullscreen( @@ -393,7 +201,35 @@ class _ClientScreenState extends State { ), actions: actions(), ), - body: content(true) + body: ClientForm( + isFullScreen: true, + client: widget.client, + nameController: nameController, + updateValidValues: (v) => setState(() => validValues = v), + identifiersControllers: identifiersControllers, + selectedTags: selectedTags, + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + enableFiltering: enableFiltering, + enableParentalControl: enableParentalControl, + enableSafeBrowsing: enableSafeBrowsing, + enableSafeSearch: enableSafeSearch, + safeSearch: safeSearch, + blockedServices: blockedServices, + updateBlockedServices: (v) => setState(() => blockedServices = v), + upstreamServers: upstreamServers, + updateUpstreamServers: (v) => setState(() => upstreamServers = v), + defaultSafeSearch: defaultSafeSearch, + useGlobalSettingsServices: useGlobalSettingsServices, + updateSelectedTags: (v) => setState(() => selectedTags = v), + updateIdentifiersControllers: (v) => setState(() => identifiersControllers = v), + enableDisableGlobalSettingsFiltering: enableDisableGlobalSettingsFiltering, + updateEnableFiltering: (v) => setState(() => enableFiltering = v), + updateEnableParentalControl: (v) => setState(() => enableParentalControl = v), + updateEnableSafeBrowsing: (v) => setState(() => enableSafeBrowsing = v), + updateEnableSafeSearch: (v) => setState(() => enableSafeSearch = v), + updateSafeSearch: (v) => setState(() => safeSearch = v), + updateUseGlobalSettingsServices: (v) => setState(() => useGlobalSettingsServices = v), + ), ), ); } @@ -431,7 +267,35 @@ class _ClientScreenState extends State { ), ), Flexible( - child: content(false) + child: ClientForm( + isFullScreen: false, + client: widget.client, + nameController: nameController, + updateValidValues: (v) => setState(() => validValues = v), + identifiersControllers: identifiersControllers, + selectedTags: selectedTags, + useGlobalSettingsFiltering: useGlobalSettingsFiltering, + enableFiltering: enableFiltering, + enableParentalControl: enableParentalControl, + enableSafeBrowsing: enableSafeBrowsing, + enableSafeSearch: enableSafeSearch, + safeSearch: safeSearch, + blockedServices: blockedServices, + updateBlockedServices: (v) => setState(() => blockedServices = v), + upstreamServers: upstreamServers, + updateUpstreamServers: (v) => setState(() => upstreamServers = v), + defaultSafeSearch: defaultSafeSearch, + useGlobalSettingsServices: useGlobalSettingsServices, + updateSelectedTags: (v) => setState(() => selectedTags = v), + updateIdentifiersControllers: (v) => setState(() => identifiersControllers = v), + enableDisableGlobalSettingsFiltering: enableDisableGlobalSettingsFiltering, + updateEnableFiltering: (v) => setState(() => enableFiltering = v), + updateEnableParentalControl: (v) => setState(() => enableParentalControl = v), + updateEnableSafeBrowsing: (v) => setState(() => enableSafeBrowsing = v), + updateEnableSafeSearch: (v) => setState(() => enableSafeSearch = v), + updateSafeSearch: (v) => setState(() => safeSearch = v), + updateUseGlobalSettingsServices: (v) => setState(() => useGlobalSettingsServices = v), + ), ) ], ), @@ -439,4 +303,5 @@ class _ClientScreenState extends State { ); } } -} \ No newline at end of file +} + diff --git a/lib/screens/clients/client/client_screen_functions.dart b/lib/screens/clients/client/client_screen_functions.dart index 4b84b2b..1f292c6 100644 --- a/lib/screens/clients/client/client_screen_functions.dart +++ b/lib/screens/clients/client/client_screen_functions.dart @@ -76,12 +76,12 @@ void openSafeSearchModal({ bool checkValidValues({ required TextEditingController nameController, - required List> identifiersControllers + required List identifiersControllers }) { if ( nameController.text != '' && identifiersControllers.isNotEmpty && - identifiersControllers[0]['controller']!.text != '' + identifiersControllers[0].controller.text != '' ) { return true; } diff --git a/lib/screens/clients/client/identifiers_section.dart b/lib/screens/clients/client/identifiers_section.dart index 3d9acf2..91a56eb 100644 --- a/lib/screens/clients/client/identifiers_section.dart +++ b/lib/screens/clients/client/identifiers_section.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -5,8 +6,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; class IdentifiersSection extends StatefulWidget { - final List> identifiersControllers; - final void Function(List>) onUpdateIdentifiersControllers; + final List identifiersControllers; + final void Function(List) onUpdateIdentifiersControllers; final void Function() onCheckValidValues; const IdentifiersSection({ @@ -41,10 +42,10 @@ class _IdentifiersSectionState extends State { child: IconButton( onPressed: () => widget.onUpdateIdentifiersControllers([ ...widget.identifiersControllers, - Map.from({ - 'id': uuid.v4(), - 'controller': TextEditingController() - }) + ControllerListItem( + id: uuid.v4(), + controller: TextEditingController() + ), ]), icon: const Icon(Icons.add) ), @@ -52,13 +53,15 @@ class _IdentifiersSectionState extends State { ], ), if (widget.identifiersControllers.isNotEmpty) ...widget.identifiersControllers.map((controller) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + padding: const EdgeInsets.only( + top: 12, bottom: 12, left: 24, right: 20 + ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: TextFormField( - controller: controller['controller'], + controller: controller.controller, onChanged: (_) => widget.onCheckValidValues(), decoration: InputDecoration( prefixIcon: const Icon(Icons.tag), @@ -72,12 +75,12 @@ class _IdentifiersSectionState extends State { ), ), ), - const SizedBox(width: 20), + const SizedBox(width: 16), Padding( padding: const EdgeInsets.only(bottom: 25), child: IconButton( onPressed: () => widget.onUpdateIdentifiersControllers( - widget.identifiersControllers.where((e) => e['id'] != controller['id']).toList() + widget.identifiersControllers.where((e) => e.id != controller.id).toList() ), icon: const Icon(Icons.remove_circle_outline_outlined) ), @@ -86,7 +89,7 @@ class _IdentifiersSectionState extends State { ), )).toList(), if (widget.identifiersControllers.isEmpty) Container( - padding: const EdgeInsets.only(top: 10), + padding: const EdgeInsets.symmetric(vertical: 16), child: Text( AppLocalizations.of(context)!.noIdentifiers, textAlign: TextAlign.center, diff --git a/lib/screens/clients/client/upstream_servers_section.dart b/lib/screens/clients/client/upstream_servers_section.dart index 47dd41d..97c8974 100644 --- a/lib/screens/clients/client/upstream_servers_section.dart +++ b/lib/screens/clients/client/upstream_servers_section.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -5,9 +6,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; class UpstreamServersSection extends StatefulWidget { - final List> upstreamServers; + final List upstreamServers; final void Function() onCheckValidValues; - final void Function(List>) onUpdateUpstreamServers; + final void Function(List) onUpdateUpstreamServers; const UpstreamServersSection({ Key? key, @@ -38,10 +39,10 @@ class _UpstreamServersSectionState extends State { padding: const EdgeInsets.only(right: 20), child: IconButton( onPressed: () => setState(() => widget.upstreamServers.add( - Map.from({ - 'id': uuid.v4(), - 'controller': TextEditingController() - }) + ControllerListItem( + id: uuid.v4(), + controller: TextEditingController() + ) )), icon: const Icon(Icons.add) ), @@ -57,7 +58,7 @@ class _UpstreamServersSectionState extends State { children: [ Expanded( child: TextFormField( - controller: controller['controller'], + controller: controller.controller, onChanged: (_) => widget.onCheckValidValues, decoration: InputDecoration( prefixIcon: const Icon(Icons.dns_rounded), @@ -70,10 +71,10 @@ class _UpstreamServersSectionState extends State { ), ), ), - const SizedBox(width: 20), + const SizedBox(width: 16), IconButton( onPressed: () => widget.onUpdateUpstreamServers( - widget.upstreamServers.where((e) => e['id'] != controller['id']).toList() + widget.upstreamServers.where((e) => e.id != controller.id).toList() ), icon: const Icon(Icons.remove_circle_outline_outlined) ) @@ -82,7 +83,7 @@ class _UpstreamServersSectionState extends State { ), )).toList(), if (widget.upstreamServers.isEmpty) Container( - padding: const EdgeInsets.only(top: 12), + padding: const EdgeInsets.symmetric(vertical: 16), child: Column( children: [ Text(